发布于 2026-01-06 1 阅读
0

如何使用 Redux Toolkit 设置 Redux

如何使用 Redux Toolkit 设置 Redux

开发现代 Web 应用程序不仅涉及 UI 构建,还涉及状态管理。Redux 是最广泛使用的 Redux 库之一。在本教程中,您将学习如何使用 2020 年最新的库和技术以及 Redux Toolkit 来设置 Redux,这将简化您的逻辑并确保您的设置具有良好的默认配置。

为什么要选择 Redux Toolkit

Redux 是入门的良好基础,但为了简化操作,建议使用 Redux Toolkit。它的创建旨在帮助解决关于 Redux 的三个常见问题:

  • 配置 Redux store 太复杂了
  • “我必须添加很多包才能让 Redux 发挥任何有用的作用。”
  • “Redux 需要编写太多样板代码”

它具备符合Redux 最佳实践的功能。它包含多个实用函数,可简化最常见的 Redux 用例,包括 store 设置、定义 reducer、使用 Immer 实现不可变更新逻辑,甚至允许一次性创建整个状态“切片”,而无需编写 action creator。

它预配置了最常用的 Redux 插件,例如用于异步逻辑的 Redux Thunk 和用于编写选择器函数的 Reselect,方便您立即使用。它还允许您覆盖所有设置,例如,您可以轻松地将其与 redux-saga 或任何其他中间件一起使用。

如何配置带有 Redux 的 Create React App

本 Redux 教程首先让我们使用 CRA 设置一个新的 React 应用程序:

npm install -g create-react-app
create-react-app redux-tutorial
cd redux-tutorial

Enter fullscreen mode Exit fullscreen mode

接下来我们将添加 Redux:

npm install --save react-redux @reduxjs/toolkit

Enter fullscreen mode Exit fullscreen mode

首先配置 store。创建文件 src/store/index.js,内容如下:

import { configureStore } from '@reduxjs/toolkit'
import { combineReducers } from 'redux'
const reducer = combineReducers({
  // here we will be adding reducers
})
const store = configureStore({
  reducer,
})
export default store;

Enter fullscreen mode Exit fullscreen mode

`configureStore` 接受单个对象而不是多个函数参数。这是因为底层 store 已配置为允许使用 Redux DevTools 扩展,并且默认包含了一些 Redux 中间件。

接下来,我们需要将我们的 store 连接到 React 应用。像这样将其导入到 index.js 中:

...
import { Provider } from 'react-redux'
import store from './store'
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

Enter fullscreen mode Exit fullscreen mode

Provider 封装了 App,整个应用程序都可以访问 Redux。如果您使用 `npm start` 启动应用程序并打开 Redux 开发工具,应该会看到 `@@INIT`。恭喜,您已成功配置 Redux!

如何构建你的 Redux

现在我们来设置 Redux 身份验证,并实现一个简单的登录表单和登录后显示的注销按钮。Redux 本身并不关心应用程序的文件夹和文件结构。但是,将特定功能的逻辑放在一起通常更容易维护代码。Redux.org 建议大多数应用程序应该使用“功能文件夹”模式(将某个功能的所有文件放在同一个文件夹中)或“鸭子模式”(将某个功能的所有 Redux 逻辑放在单个文件中)来组织文件,而不是按代码“类型”(reducer、action 等)将逻辑分散到不同的文件夹中。

让我们添加 src/store/user.js 存储切片:

import { createSlice } from '@reduxjs/toolkit'
// Slice
const slice = createSlice({
  name: 'user',
  initialState: {
    user: null,
  },
  reducers: {
    loginSuccess: (state, action) => {
      state.user = action.payload;
    },
    logoutSuccess: (state, action) =>  {
      state.user = null;
    },
  },
});
export default slice.reducer
// Actions
const { loginSuccess, logoutSuccess } = slice.actions
export const login = ({ username, password }) => async dispatch => {
  try {
    // const res = await api.post('/api/auth/login/', { username, password })
    dispatch(loginSuccess({username}));
  } catch (e) {
    return console.error(e.message);
  }
}
export const logout = () => async dispatch => {
  try {
    // const res = await api.post('/api/auth/logout/')
    return dispatch(logoutSuccess())
  } catch (e) {
    return console.error(e.message);
  }
}

Enter fullscreen mode Exit fullscreen mode

商店功能文件包含 createSlice,它返回一个“slice”对象,该对象包含一个名为 reducer 的字段,其中包含生成的 reducer 函数,以及一个名为 actions 的对象,其中包含生成的 action creators。

在底部,我们可以导入操作创建器并直接导出它们,或者在异步操作(如登录和注销)中使用它们。

要将 reducer 连接到 Redux,我们需要将其添加到 store/index.js 中的主 reducer 中:

...
import user from './user'
const reducer = combineReducers({
  user,
})

Enter fullscreen mode Exit fullscreen mode

使用 useDispatch 和 useSelector 将 Redux 连接到组件

我们的 Redux 配置已经完成。现在让我们配置身份验证表单。为此,我们将使用 Formik。请在终端中输入以下命令:

npm install --save formik

Enter fullscreen mode Exit fullscreen mode

现在我们可以创建以下 src/App.js 组件:

...
import {useDispatch, useSelector} from 'react-redux'
import {Field, Form, Formik} from 'formik'
import {login, logout} from './store/user'
function App() {
  const dispatch = useDispatch()
  const { user } = useSelector(state => state.user)
  if (user) {
    return (
      <div>
        Hi, {user.username}!
        <button onClick={() => dispatch(logout())}>Logout</button>
      </div>
    )
  }
  return (
    <div>
      <Formik
        initialValues={{ username: '', password: '' }}
        onSubmit={(values) => { dispatch(login(values)) }}
      >
        {({ isSubmitting }) => (
          <Form>
            <Field type="text" name="username" />
            <Field type="password" name="password" />
            <button type="submit" disabled={isSubmitting}>Login</button>
          </Form>
        )}
      </Formik>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

请注意,这里不再需要 connect!有了 useDispatch 和 useSelector,我们现在可以使用 hooks 将 Redux 集成到纯组件中!我们只需要用 Provider 包裹 App,而且相比 connect,样板代码要少得多。

如何在页面重新加载时保持用户身份验证

您可能已经注意到,每次页面重新加载时,身份验证都会被重置。

使用 localStorage 可以轻松解决这个问题,只需在 src/store/user.js 文件中添加几行代码即可。

+const initialUser = localStorage.getItem('user')
+  ? JSON.parse(localStorage.getItem('user'))
+  : null
+
const slice = createSlice({
  name: 'user',
  initialState: {
-    user: null,
+    user: initialUser,
  },
  reducers: {
    loginSuccess: (state, action) => {
      state.user = action.payload;
+      localStorage.setItem('user', JSON.stringify(action.payload))
    },
    logoutSuccess: (state, action) =>  {
      state.user = null;
+      localStorage.removeItem('user')
    },
  },
});

Enter fullscreen mode Exit fullscreen mode

如何存储令牌

我最喜欢的 API 客户端库是 Axios。我更喜欢 Axios 而不是内置 API,因为它易于使用,而且还有一些额外的功能,例如 XSRF 令牌支持和拦截器。

以下是我常用的一个配置示例:

const api = axios.create({
  baseURL: '/',
  headers: {
    'Content-Type': 'application/json'
  },
})
api.interceptors.request.use(
  config => {
    const token = localStorage.getItem('token')
    if (token) {
      config.headers['Authorization'] = `Token ${token}`
    }
    return config
  },
  error => Promise.reject(error)
)
export default api

Enter fullscreen mode Exit fullscreen mode

登录后如何重定向

在 Redux 操作后重定向用户的最简单方法是使用 React 提供的 Redirect 组件。

这可以是登录表单组件中的一个示例,例如使用如下代码:

if (user) {
    return (
      <Redirect to={'/home'} />
    )
  }

Enter fullscreen mode Exit fullscreen mode
文章来源:https://dev.to/rubengabrielian/how-to-setup-redux-with-redux-toolkit-5fgh