← 目录从零开始学习React

React博客项目

2024/9/21

创建一个带有用户登录功能的博客应用,使用 React 路由进行页面跳转,并使用 Context API 或 Redux 来管理全局状态。下面是一个示例项目结构,包括登录、博客页面、和全局状态管理。

我们将分步骤展示如何实现:

  1. 使用 React Router 进行页面路由
  2. 使用 Context API 或 Redux 进行全局状态管理
  3. 创建登录和博客页面,并实现登录逻辑
  4. 页面跳转和状态管理

项目文件结构

text
/src
  /components
    - Blog.js
    - Home.js
    - Login.js
    - Navbar.js
  /context
    - AuthContext.js
  /store (如果使用 Redux)
    - store.js
    - authSlice.js
  - App.js
  - index.js

1. 项目初始化与安装依赖

首先,使用 npx create-react-app 创建一个新项目,并安装必要的依赖。

bash
npx create-react-app react-blog
cd react-blog
npm install react-router-dom

如果使用 Redux,还需要安装 Redux 及其工具包:

bash
npm install @reduxjs/toolkit react-redux

2. 使用 React Router 配置路由

2.1 App.js

jsx
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from './components/Home';
import Blog from './components/Blog';
import Login from './components/Login';
import Navbar from './components/Navbar';

function App() {
  return (
    <Router>
      <Navbar />
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/blog" element={<Blog />} />
        <Route path="/login" element={<Login />} />
      </Routes>
    </Router>
  );
}

export default App;
  • BrowserRouter 包裹整个应用,Routes 包含多个 Route,每个路由对应不同的页面。
  • Navbar 为导航栏,允许用户在不同页面间跳转。

2.2 Navbar.js - 导航组件

jsx
import React from 'react';
import { Link } from 'react-router-dom';

function Navbar() {
  return (
    <nav>
      <ul>
        <li>
          <Link to="/">Home</Link>
        </li>
        <li>
          <Link to="/blog">Blog</Link>
        </li>
        <li>
          <Link to="/login">Login</Link>
        </li>
      </ul>
    </nav>
  );
}

export default Navbar;

3. 使用 Context API 进行全局状态管理

为了演示登录逻辑,使用 Context API 管理全局的用户登录状态。

3.1 创建 AuthContext.js

jsx
import React, { createContext, useState, useContext } from 'react';

const AuthContext = createContext();

export const useAuth = () => useContext(AuthContext);

export function AuthProvider({ children }) {
  const [user, setUser] = useState(null); // null 表示未登录

  const login = (username) => {
    setUser({ username });
  };

  const logout = () => {
    setUser(null);
  };

  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
}
  • AuthContext:提供登录状态。
  • login 和 logout 方法用于改变用户登录状态。

3.2 在 App.js 中引入 AuthProvider

jsx
import { AuthProvider } from './context/AuthContext';

function App() {
  return (
    <AuthProvider>
      <Router>
        <Navbar />
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/blog" element={<Blog />} />
          <Route path="/login" element={<Login />} />
        </Routes>
      </Router>
    </AuthProvider>
  );
}
  • AuthProvider 包裹整个应用,提供全局的登录状态。

4. 创建登录页面

4.1 Login.js

jsx
import React, { useState } from 'react';
import { useAuth } from '../context/AuthContext';
import { useNavigate } from 'react-router-dom';

function Login() {
  const [username, setUsername] = useState('');
  const { login } = useAuth();
  const navigate = useNavigate();

  const handleSubmit = (e) => {
    e.preventDefault();
    login(username); // 执行登录逻辑
    navigate('/blog'); // 登录后跳转到博客页面
  };

  return (
    <div>
      <h2>Login</h2>
      <form onSubmit={handleSubmit}>
        <input 
          type="text" 
          value={username}
          onChange={(e) => setUsername(e.target.value)} 
          placeholder="Enter username"
          required 
        />
        <button type="submit">Login</button>
      </form>
    </div>
  );
}

export default Login;
  • 用户输入用户名后提交登录表单,通过 useAuth 的 login 方法更改全局状态,并通过 useNavigate 跳转到博客页面。

5. 博客页面与状态显示

5.1 Blog.js

jsx
import React from 'react';
import { useAuth } from '../context/AuthContext';
import { useNavigate } from 'react-router-dom';

function Blog() {
  const { user, logout } = useAuth();
  const navigate = useNavigate();

  const handleLogout = () => {
    logout(); // 执行登出
    navigate('/'); // 登出后跳转到主页
  };

  if (!user) {
    return <p>You need to log in to see the blog content.</p>;
  }

  return (
    <div>
      <h2>Welcome to the Blog, {user.username}!</h2>
      <button onClick={handleLogout}>Logout</button>
    </div>
  );
}

export default Blog;
  • 如果用户未登录,将显示提示信息。如果用户已登录,将显示博客内容及登出按钮。

6. 主页

6.1 Home.js

jsx
import React from 'react';

function Home() {
  return (
    <div>
      <h2>Home Page</h2>
      <p>Welcome to the blog application!</p>
    </div>
  );
}

export default Home;

7. 使用 Redux 进行状态管理(可选)

如果使用 Redux 来管理登录状态,可替代 Context API。创建一个 authSlice.js 来管理登录逻辑。

7.1 authSlice.js

javascript
import { createSlice } from '@reduxjs/toolkit';

const authSlice = createSlice({
  name: 'auth',
  initialState: { user: null },
  reducers: {
    login(state, action) {
      state.user = { username: action.payload };
    },
    logout(state) {
      state.user = null;
    },
  },
});

export const { login, logout } = authSlice.actions;
export default authSlice.reducer;

7.2 配置 store.js

javascript
import { configureStore } from '@reduxjs/toolkit';
import authReducer from './authSlice';

const store = configureStore({
  reducer: {
    auth: authReducer,
  },
});

export default store;

7.3 在 App.js 中使用 Redux

jsx
import { Provider } from 'react-redux';
import store from './store';

function App() {
  return (
    <Provider store={store}>
      <Router>
        <Navbar />
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/blog" element={<Blog />} />
          <Route path="/login" element={<Login />} />
        </Routes>
      </Router>
    </Provider>
  );
}

export default App;

7.4 使用 useSelector 和 useDispatch 在组件中获取和更新状态

在 Login.js 和 Blog.js 中,使用 useSelector 获取用户状态,使用 useDispatch 执行登录和登出操作。


总结

这个项目展示了如何使用 React Router、Context API 或 Redux 来实现一个带有用户登录功能的博客应用。通过使用路由进行页面跳转和全局状态管理,用户可以登录后访问博客内容,并在退出后重新回到首页。