React中Redux基础和路由介绍

发布于:2025-07-13 ⋅ 阅读:(13) ⋅ 点赞:(0)

目录

React项目结构介绍 

一、Redux基础使用 

1. 项目初始化

2. 定义 Slice(使用 Redux Toolkit)

3. 配置 Store

4. 应用 Store 到 React

5. 在组件中使用状态

6. 异步操作(Thunk)

核心概念总结

二、React路由介绍 

安装 React Router

1. 基础概念

2. 基本使用示例

在 App.jsx 中设置基础路由

创建简单的页面组件

路由导航

1. 使用<Link> 组件进行导航

编程式导航

1使用 useNavigate 实现编程式导航

基本用法

2. navigate 方法的参数

3. 相对路径导航

示例:相对路径跳转

4. 编程式导航与条件判断

示例:根据条件判断进行导航

5. 返回上一页

示例:返回上一页

6. 跳转到首页或其他默认页面

示例:跳转到首页

7. 编程式导航与路由守卫

示例:路由守卫与编程式导航

总结


React项目结构介绍 

my-app/
├── public/                     # 静态资源文件夹
│   ├── index.html              # HTML 模板
│   ├── favicon.ico             # 网站图标
│   └── assets/                 # 静态资源(图片、字体等)
├── src/
│   ├── assets/                 # 存放项目中的静态资源(如图片、字体等)
│   ├── components/             # 可复用的 UI 组件
│   ├── hooks/                  # 自定义 Hook
│   ├── pages/                  # 页面组件(对应不同的路由)
│   ├── routes/                 # 路由配置文件
│   │   └── index.js            # 路由配置文件(定义页面组件的路径映射)
│   ├── services/               # 与 API 交互的服务层(如数据获取、身份验证)
│   ├── store/                  # 状态管理(如 Redux 或 Context API)
│   ├── utils/                  # 工具函数
│   ├── App.js                  # 根组件
│   ├── index.js                # React 入口文件
│   └── styles/                 # 全局样式或主题文件
├── .gitignore                  # Git 忽略文件
├── package.json                # 项目信息和依赖管理
├── README.md                   # 项目说明文件
└── package-lock.json / yarn.lock  # 锁定依赖的版本

一、Redux基础使用 

1. 项目初始化

要先创建一个 React 项目,并且安装 Redux 和 React-Redux。

npx create-react-app redux-demo
cd redux-demo
npm install redux react-redux @reduxjs/toolkit

2. 定义 Slice(使用 Redux Toolkit)

src/features/counter/counterSlice.js文件中定义一个计数器的 slice。

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

const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    value: 0,
  },
  reducers: {
    increment: (state) => {
      state.value += 1;
    },
    decrement: (state) => {
      state.value -= 1;
    },
    incrementByAmount: (state, action) => {
      state.value += action.payload;
    },
  },
});

export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;

1. reducers 的作用

在 Redux Toolkit 中,reducers 是 createSlice 函数的核心配置项,用于定义状态修改逻辑。它的主要作用是:

  • 自动生成 Action creators 和 Action types:无需手动编写 action 常量和 action 创建函数。
  • 简化 Redux 逻辑:允许使用 "mutating" 语法(如 state.value += 1),底层通过 Immer 库自动转换为不可变更新。
  • 集中管理状态逻辑:将 action 和 reducer 放在同一个文件中,提高代码可维护性。

counterSlice.js 文件中:

  • incrementdecrementincrementByAmount 都是action creators
  • 每个函数内部的 state 参数是当前状态的副本,修改后会自动生成新的状态。

3. 配置 Store

src/store.js文件中配置 store。

import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './features/counter/counterSlice';

export const store = configureStore({
  reducer: {
    counter: counterReducer,
  },
});

4. 应用 Store 到 React

src/index.js文件中使用 Provider 包裹应用。

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { store } from './store';
import { Provider } from 'react-redux';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>
    <App />
  </Provider>
);

5. 在组件中使用状态

src/App.js组件中使用 Redux 状态。

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, incrementByAmount } from './features/counter/counterSlice';

function App() {
  // 获取状态
  const count = useSelector((state) => state.counter.value);
  // 获取dispatch函数
  const dispatch = useDispatch();

  return (
    <div className="App">
      <h1>计数器: {count}</h1>
      <button onClick={() => dispatch(increment())}>+</button>
      <button onClick={() => dispatch(decrement())}>-</button>
      <button onClick={() => dispatch(incrementByAmount(5))}>+5</button>
    </div>
  );
}

export default App;

6. 异步操作(Thunk)

若需要进行异步操作,可使用 createAsyncThunk

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import axios from 'axios';

// 创建异步thunk
export const fetchUserById = createAsyncThunk(
  'users/fetchByIdStatus',
  async (userId) => {
    const response = await axios.get(`/api/users/${userId}`);
    return response.data;
  }
);

const usersSlice = createSlice({
  name: 'users',
  initialState: { entities: [], loading: 'idle' },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchUserById.pending, (state) => {
        state.loading = 'pending';
      })
      .addCase(fetchUserById.fulfilled, (state, action) => {
        state.loading = 'idle';
        state.entities.push(action.payload);
      });
  },
});

export default usersSlice.reducer;

核心概念总结

  • Store:它是应用状态的容器,一个应用只能有一个 store。
  • Reducer:这是一个纯函数,负责处理 action 并返回新的状态。
  • Action:它是一个描述状态变化的对象,通过 dispatch 来触发。
  • Selector:用于从 store 中选择特定的状态。
  • useSelector:这是一个 React Hook,能让组件从 store 中读取状态。
  • useDispatch:这也是一个 React Hook,可让组件派发 action。

二、React路由介绍 

安装 React Router

首先,你需要安装 react-router-dom,这是 React Router 为 Web 应用提供的包。

npm install react-router-dom

1. 基础概念

  • BrowserRouter: 使用 HTML5 的 history API(pushState、replaceState 和 popstate 事件)来保持 UI 同步。
  • Routes: 路由容器,用于包裹多个 Route 组件。
  • Route: 定义了路径与组件之间的映射关系,当 URL 匹配时显示对应的组件。
  • Link: 用于创建导航链接,不会导致页面刷新。
  • NavLink: 类似于 Link,但可以添加样式以指示当前激活的导航项。
  • Navigate(v6+): 提供编程式导航的能力。
  • useParamsuseSearchParamsuseNavigateuseLocation: 这些 hooks 可以让你访问路由参数、查询参数、执行导航操作以及获取当前的位置信息。

2. 基本使用示例

在 App.jsx 中设置基础路由
// src/App.jsx
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import HomePage from './pages/HomePage';
import AboutPage from './pages/AboutPage';
import NotFoundPage from './pages/NotFoundPage';

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<HomePage />} />
        <Route path="/about" element={<AboutPage />} />
        <Route path="*" element={<NotFoundPage />} /> {/* 404 页面 */}
      </Routes>
    </Router>
  );
}

export default App;
创建简单的页面组件
// src/pages/HomePage.jsx
import React from 'react';

function HomePage() {
  return <h1>Home Page</h1>;
}

export default HomePage;

路由导航

1. 使用 <Link><NavLink> 组件进行导航

<Link> 是 React Router 中用于路由导航的最基础组件,它通过创建一个 <a> 标签,帮助用户在不同的路由之间进行跳转。<Link> 组件会自动拦截浏览器的默认行为,避免页面的完全刷新,保持单页应用(SPA)的特性。
<NavLink><Link> 的一个增强版,它用于自动添加激活样式,帮助你标识当前访问的页面。你可以使用 activeClassName(React Router v5)或者 className(React Router v6)来定义激活链接的样式。

在 React Router v6 中,activeClassName 已被 className 属性替代,className 会根据是否为当前活动路由自动添加特定的样式。

// src/components/Navigation.jsx
import React from 'react';
import { Link, NavLink } from 'react-router-dom';

function Navigation() {
  return (
    <nav>
      <ul>
        <li><Link to="/">Home</Link></li>
        <li><NavLink to="/about">About</NavLink></li>
      </ul>
    </nav>
  );
}

export default Navigation;

编程式导航

1. 使用 useNavigate 实现编程式导航

在 React Router v6 中,useNavigate 是用来执行编程式导航的钩子。它返回一个函数,可以用来触发路由的跳转。你可以在事件处理函数、生命周期钩子中,或根据某些条件动态地进行路由跳转。

基本用法
import { useNavigate } from 'react-router-dom';

function MyComponent() {
  const navigate = useNavigate();  // 获取导航函数

  const handleClick = () => {
    navigate('/about');  // 跳转到 /about 路径
  };

  return <button onClick={handleClick}>Go to About</button>;
}

在上面的例子中,当用户点击按钮时,navigate('/about') 会将用户导航到 /about 路由。

2. navigate 方法的参数

navigate 函数可以接收两个参数:

  1. 目标路径 (to): 这是跳转的目标路径,可以是相对路径或绝对路径。

  2. 选项 (options): 这是一个可选对象,允许你配置更多导航行为。常用的选项包括:

    • replace:指定是否替换当前历史记录(类似浏览器的 window.location.replace())。如果设为 true,跳转后当前历史记录将被替换,用户不能按浏览器的“后退”按钮返回。

    • state:你可以通过 state 传递一些状态数据,跳转时携带。

    • relative:指定相对路径跳转。

示例:使用 replacestate

import { useNavigate } from 'react-router-dom';

function SubmitForm() {
  const navigate = useNavigate();

  const handleSubmit = () => {
    // 跳转并替换历史记录
    navigate('/thank-you', { replace: true, state: { fromForm: true } });
  };

  return <button onClick={handleSubmit}>Submit</button>;
}

在这个例子中,navigate('/thank-you', { replace: true, state: { fromForm: true } }):

  • 会跳转到 /thank-you 页面。

  • 通过 replace: true 来替换当前历史记录,避免用户按“后退”按钮返回到表单页。

  • 通过 state 参数将一些额外的状态数据传递给目标页面。

3. 相对路径导航

React Router v6 支持相对路径导航,允许你在同一层级的路径上执行跳转。你可以使用相对路径来避免硬编码目标路径。相对路径跳转 是一种基于当前路由上下文的路径跳转方式。它并不依赖于指定一个完整的绝对路径,而是基于当前所在的路由(父路由)计算跳转的目标路径。这种方式通常用于跳转到 当前路由的子路由 或与当前路径相关的目标路径。

路由层级示意图

/
├── /login                        // 登录页
├── /register                     // 注册页
├── /home                         // 首页
└── /dashboard                    // 仪表盘
    ├── /user/:id                 // 用户资料页面
    │   ├── /user/:id/edit        // 编辑资料页面
    │   └── /user/:id/settings    // 用户设置页面
    ├── /articles                 // 文章列表页
    │   ├── /articles/new         // 创建文章页面
    │   └── /articles/:id/edit    // 编辑文章页面
    └── /publish                  // 发布文章页面
示例:相对路径跳转
import { useNavigate } from 'react-router-dom';

function UserProfile() {
  const navigate = useNavigate();

  const goToEditPage = () => {
    navigate('edit');  // 相对路径跳转,跳转到 /user/:id/edit
  };

  return <button onClick={goToEditPage}>Edit Profile</button>;
}

在上面的例子中,navigate('edit') 是相对路径跳转,它会将用户跳转到 /user/:id/edit,其中 :id 是当前页面的动态参数。

4. 编程式导航与条件判断

编程式导航经常与条件判断结合使用,可以根据某些业务逻辑决定是否进行跳转。例如,当用户登录状态发生变化时,或者表单验证通过后,跳转到另一个页面。

示例:根据条件判断进行导航
import { useNavigate } from 'react-router-dom';

function LoginPage() {
  const navigate = useNavigate();
  const [isAuthenticated, setIsAuthenticated] = useState(false);

  const handleLogin = (credentials) => {
    // 假设验证通过
    if (credentials.username === 'user' && credentials.password === 'password') {
      setIsAuthenticated(true);
      navigate('/dashboard');  // 登录成功后跳转到 dashboard 页面
    } else {
      alert('Invalid credentials');
    }
  };

  return (
    <div>
      <button onClick={() => handleLogin({ username: 'user', password: 'password' })}>
        Login
      </button>
    </div>
  );
}

在这个例子中,用户点击登录按钮后,handleLogin 函数会根据条件判断登录是否成功。如果成功,调用 navigate('/dashboard') 来跳转到 /dashboard 页面。

5. 返回上一页

通过 navigate(),你不仅可以跳转到指定的页面,还可以通过传递负数的参数来模拟浏览器的“后退”功能。

示例:返回上一页
import { useNavigate } from 'react-router-dom';

function GoBackButton() {
  const navigate = useNavigate();

  const goBack = () => {
    navigate(-1);  // 返回上一页,相当于浏览器的 back 按钮
  };

  return <button onClick={goBack}>Go Back</button>;
}

在上面的例子中,navigate(-1) 会使用户返回到历史记录栈中的上一页,相当于浏览器的 "Back" 按钮。

6. 跳转到首页或其他默认页面

navigate() 还可以用来重定向用户到首页或其他默认页面。

示例:跳转到首页
import { useNavigate } from 'react-router-dom';

function LogoutButton() {
  const navigate = useNavigate();

  const handleLogout = () => {
    // 清除用户登录信息
    localStorage.removeItem('authToken');
    navigate('/');  // 登出后跳转到首页
  };

  return <button onClick={handleLogout}>Logout</button>;
}

在这个例子中,用户点击登出按钮后,navigate('/') 会将用户重定向到首页。

7. 编程式导航与路由守卫

在某些情况下,你可能希望在进行导航之前检查某些条件,如用户是否已经登录,或者是否有权限访问某些页面。如果没有满足条件,可以直接跳转到登录页或错误页面。

示例:路由守卫与编程式导航
import { useNavigate } from 'react-router-dom';

function ProtectedPage() {
  const navigate = useNavigate();
  const isAuthenticated = localStorage.getItem('authToken');

  if (!isAuthenticated) {
    navigate('/login');  // 如果用户未认证,则重定向到登录页
    return null;
  }

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

在上面的例子中,ProtectedPage 组件会在渲染之前检查用户是否已认证。如果没有认证,调用 navigate('/login') 重定向用户到登录页面。

总结

编程式导航在 React Router 中非常重要,它允许你在应用中通过代码控制路由跳转,适用于动态场景或根据条件触发跳转。常见的编程式导航方式如下:

  • useNavigate 钩子:通过 navigate() 函数实现导航。

  • 跳转到指定路径navigate('/path')

  • 替换历史记录navigate('/path', { replace: true })

  • 传递状态数据navigate('/path', { state: data })

  • 相对路径跳转navigate('sub-path')

  • 返回上一页navigate(-1)

编程式导航的常见应用场景包括表单提交后跳转、登录验证、路由守卫、动态跳转等。

 


网站公告

今日签到

点亮在社区的每一天
去签到