题目 57 - 题目 64
57. 你在 React 项目中是如何使用 Redux 的? 项目结构是如何划分的?
- 在 React 项目中使用 Redux 的流程
1.1 安装与配置 Redux
- 安装依赖:首先安装 Redux 和 React-Redux,通常还会使用 Redux Toolkit 来简化 Redux 的使用。
测试代码
npm install redux react-redux @reduxjs/toolkit
创建 Store:使用 Redux Toolkit 的 configureStore 方法来创建 Redux 的 store。
测试代码
import { configureStore } from '@reduxjs/toolkit'
import rootReducer from './reducers'
const store = configureStore({
reducer: rootReducer
})
export default store
1.2 创建 Reducer 和 Action
- 定义 Slice:在 Redux Toolkit 中,通常使用 createSlice 方法来定义 reducer 和 action。
测试代码
import { createSlice } from '@reduxjs/toolkit'
const counterSlice = createSlice({
name: 'counter',
initialState: 0,
reducers: {
increment: state => state + 1,
decrement: state => state - 1
}
})
export const { increment, decrement } = counterSlice.actions
export default counterSlice.reducer
1.3 连接 Redux 与 React
- 提供 Store:使用 Provider 组件将 Redux store 提供给整个应用。
测试代码
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import store from './store'
import App from './App'
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
- 使用状态和派发动作:使用 useSelector 获取状态,使用 useDispatch 派发动作。
测试代码
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { increment, decrement } from './counterSlice'
function Counter() {
const count = useSelector(state => state.counter)
const dispatch = useDispatch()
return (
<div>
<button onClick={() => dispatch(decrement())}>-</button>
<span>{count}</span>
<button onClick={() => dispatch(increment())}>+</button>
</div>
)
}
export default Counter
- 项目结构的划分
2.1 典型的 Redux 项目结构
- src/
- components/:用于存放无状态的展示组件,通常只负责 UI 渲染。
- features/ 或 slices/:用于存放 Redux 相关的逻辑,每个功能模块一个文件夹。
- counterSlice.js:定义 slice 和相关的 actions、reducers。
- reducers/:用于存放 rootReducer 和其他手动管理的 reducers。
- index.js:组合所有 reducers。
- store/:用于存放 Redux 的 store 配置文件。
- index.js:创建并导出 Redux store。
- App.js:应用的根组件,通常在这里引入 Provider。
- index.js:入口文件,渲染根组件。
58.说说对 Redux 中间件的理解?常用的中间件有哪些?实现原理?
常用的中间件
有很多优秀的 redux 中间件,如:
- redux-thunk:用于异步操作
- redux-logger:用于日志记录
上述的中间件都需要通过 applyMiddlewares 进行注册,作用是将所有的中间件组成一个数组,依次执行
然后作为第二个参数传入到 createStore 中
测试代码
const store = createStore(reducer, applyMiddleware(thunk, logger))
redux-thunk
redux-thunk 是官网推荐的异步处理中间件
默认情况下的 dispatch(action),action 需要是一个 JavaScript 的对象
redux-thunk 中间件会判断你当前传进来的数据类型,如果是一个函数,将会给函数传入参数值(dispatch,getState)
- dispatch 函数用于我们之后再次派发 action
- getState 函数考虑到我们之后的一些操作需要依赖原来的状态,用于让我们可以获取之前的一些状态
测试代码
const getHomeMultidataAction = () => {
return dispatch => {
axios.get('http://xxx.xx.xx.xx/test').then(res => {
const data = res.data.data
dispatch(changeBannersAction(data.banner.list))
dispatch(changeRecommendsAction(data.recommend.list))
})
}
}
redux-logger
如果想要实现一个日志功能,则可以使用现成的 redux-logger
测试代码
import { applyMiddleware, createStore } from 'redux'
import createLogger from 'redux-logger'
const logger = createLogger()
const store = createStore(reducer, applyMiddleware(logger))