DEV Community

Usool
Usool

Posted on

Transitioning from Flask with Jinja2 to React: Understanding Authentication and Data Flow for Beginners

If you're a fullstack developer (especially React & Python) transitioning your web application from using Flask with Jinja2 templates to a modern React frontend, you might feel a bit overwhelmed. Questions like "Can I still use Jinja2 with React?" and "How do I handle authentication now?" are common. This guide will clarify these questions and show you how to make the transition smoother.


Understanding the Key Difference: Jinja2 vs React

Jinja2

Jinja2 is a server-side templating engine used in Flask. It allows you to dynamically render HTML templates by passing data from the server to the frontend.

  • How it works: Flask renders an HTML template on the server and sends it to the client. Data is embedded directly into the HTML using syntax like {{ variable }}.

React

React is a client-side library for building interactive user interfaces. Instead of receiving pre-rendered HTML, the browser downloads a JavaScript bundle. React then uses this bundle to render HTML dynamically in the browser.

  • How it works: React fetches data from an API (e.g., Flask backend) and renders the UI based on this data.

Can You Use Jinja2 with React?

The short answer is no. React is a client-side framework, while Jinja2 is server-side. React does not render HTML on the server, so Jinja2 templates are not compatible.

Solution

You need to convert your Flask application into an API-first backend that serves JSON responses instead of HTML. React will consume these APIs to fetch and display data.


How to Handle Authentication with React and Flask?

Authentication is another critical change. Flask-Login is great for server-rendered apps, but it's not ideal for React. Here's why:

  • Flask-Login uses session-based authentication, which relies on cookies managed by the server.
  • React apps typically use token-based authentication, such as JWT (JSON Web Tokens), for better compatibility with REST APIs.

JWT Authentication: The React-Friendly Way

JWT is a stateless authentication mechanism that works seamlessly with React. Here’s how you can implement it:

1. Backend Setup (Flask)

Install the required library:

pip install flask-jwt-extended
Enter fullscreen mode Exit fullscreen mode

Add JWT-based authentication to your Flask app:

from flask import Flask, request, jsonify
from flask_jwt_extended import (
    JWTManager, create_access_token, jwt_required, get_jwt_identity
)

app = Flask(__name__)
app.config['JWT_SECRET_KEY'] = 'your_secret_key'  # Change this to a secure key
jwt = JWTManager(app)

# Dummy user database
users = {"user1": "password123", "user2": "mypassword"}

@app.route('/login', methods=['POST'])
def login():
    username = request.json.get('username')
    password = request.json.get('password')

    if username in users and users[username] == password:
        access_token = create_access_token(identity=username)
        return jsonify(access_token=access_token)
    return jsonify({"msg": "Invalid credentials"}), 401

@app.route('/protected', methods=['GET'])
@jwt_required()
def protected():
    current_user = get_jwt_identity()
    return jsonify(logged_in_as=current_user), 200

if __name__ == '__main__':
    app.run(debug=True)
Enter fullscreen mode Exit fullscreen mode
  • Login Route: Verifies credentials and returns a JWT token.
  • Protected Route: Accessible only if a valid JWT is sent in the Authorization header.

2. Frontend Setup (React)

Use fetch or axios in your React app to communicate with the Flask backend.

Example React Login Form:

import React, { useState } from 'react';

function Login() {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [token, setToken] = useState('');

  const handleLogin = async () => {
    const response = await fetch('http://localhost:5000/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ username, password }),
    });

    const data = await response.json();
    if (data.access_token) {
      setToken(data.access_token);
      localStorage.setItem('token', data.access_token); // Store token
    } else {
      alert('Invalid credentials');
    }
  };

  return (
    <div>
      <input
        type="text"
        placeholder="Username"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
      />
      <input
        type="password"
        placeholder="Password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
      />
      <button onClick={handleLogin}>Login</button>
    </div>
  );
}

export default Login;
Enter fullscreen mode Exit fullscreen mode

Example of Accessing Protected Routes:

import React, { useEffect } from 'react';

function ProtectedPage() {
  useEffect(() => {
    const token = localStorage.getItem('token');
    fetch('http://localhost:5000/protected', {
      headers: { Authorization: `Bearer ${token}` },
    })
      .then((response) => response.json())
      .then((data) => console.log(data))
      .catch((err) => console.error(err));
  }, []);

  return <h1>Protected Content</h1>;
}

export default ProtectedPage;
Enter fullscreen mode Exit fullscreen mode

How Does JWT Work?

  1. User logs in: Flask verifies the credentials and issues a JWT.
  2. React stores the JWT: In localStorage or an HttpOnly cookie.
  3. Subsequent requests: React includes the JWT in the Authorization header (Bearer <token>).
  4. Flask validates the token: On every request, the backend checks the token's validity and grants/denies access.

Alternative: Continue with Flask-Login

If you want to stick with Flask-Login for session-based authentication:

  • React can send login requests, and Flask-Login will manage the session via cookies.
  • This approach is less common for SPAs but works for specific use cases.

Final Thoughts

Switching from Jinja2 to React is a shift from server-side to client-side rendering. With React, you'll need to adapt your Flask backend to serve as an API, and JWT is the recommended authentication method. Here's a summary of what you’ve learned:

  • Data Flow: Replace Jinja2 with JSON responses from Flask.
  • Authentication: Use JWT for stateless, token-based authentication.
  • React Integration: Fetch data and include tokens in API calls.

Have any questions or tips? Let me know in the comments below! 👇

Top comments (0)