在开发的过程中突然发现了一个非常诡异的问题,伪代码如下:
this.props.dispatch(updateData(value)) // 1
console.log(this.props.data)//2 状态没有更新
setTimeout(() => //3 状态发生了更新)
于是猜想redux执行action应该是同步的,但是reducer中将新状态返回更新store数据仓库的过程应该是异步的.所以当上面1处修改store中的数据,2中获取时却不是更新的数据,因为此时store仓库的数据还未更新.
通过搜索相关网页得到一些启示:组件通过react-redux封装后相当于包了一层高阶组件。而这一个高阶组件在redux里的state更新时会调用setState,所以它的store的数据仓库更新才会是异步的过程.
解决方法:
action中:
export const updateData = (value) => dispatch => {
dispatch({
type: 'UPDATE_DATA',
value,
return Promise.resolve();//通过返回promise解决状态异步更新的问题
组件中使用:
this.props.actions.updateData(value).then(()=>{
console.log(this.props.data) //状态更新了,获取到的是最新的状态值
在开发的过程中突然发现了一个非常诡异的问题,伪代码如下:this.props.dispatch(updateData(value)) // 1console.log(this.props.data)//2 状态没有更新setTimeout(() => //3 状态发生了更新) 于是猜想redux执行action应该是同步的,但是reducer中将新状态返回更新store数...
redux
通过 dispatch(action) -> 中间件 -> reducer处理数据 -> 改变store -> 使用subscribe()监听store改变更新视图 的方式管理状态
将所有状态存储在一个store对象里面
reducer为纯函数,而异步操作由于结果的不确定性所以含有副作用,所以需要特殊处理
react-redux
容器组件,负责管理数据和业务逻辑,不负责UI呈现
UI组件,提供UI呈现,无状态即不使用this.state,状态全部由this.props提供
由connect生成容器组件,每次store改变会调用conn
首先,假设我希望在Count这个UI组件中用到一个redux的对象count,是不能直接使用的。需要在Count这个UI组件外包裹一个容器组件Count,容器组件才能操作state里面的数据和发布action,然后Count的容器组件通过props把state的数据和改变数据的方法也就是action传给UI组件。
那么首先要知道,怎么把Count的UI组件和Count.
问题描述
在使用
react-redux中,reducer的数据明明已经更改了,但是却不能触发组件的render函数,页面也
没有同步
更新。看了网上的一些答案,才知道在reducer
中一般不对前一个状态pre
State进行数据上的操作,因为当你返回pre
State时,
react-redux并不知道数据已经更改(pre
State是对象引用,始终指向一个地址),而我在这里对pre
State进行了push操作,并把操作后的pre
State返回。
解决方法
改正后的代码如下:
写在最后:若有误,请指正。
Mutation必须是同步函数
vuex和
redux都是一种状态管理机制。然后他们会有自己的
state(状态)和修改
state的方法,修改
state的方法涉及到同步和
异步,vuex的处理方式是同步在mutation里面,
异步在actions里面,然后
redux的同步就是reducer,
异步更多的是用户自己去通过
中间件的方式去实现
reducer的
更新state异步更改为同步
有些需求比如:我们想在接口请求完成后立即获取
state的状态,然后去做路由跳转等等操作,但是
redux中action操作的
state都是
异步的,怎么办呢?下面我们看一个例子
在actions
中方法
中返回Promise即可:
export default {
loginSuccess (
dispatch) {
return
dispatch => {
dispatch({
1:发送异步请求是在componentDidMount这个生命周期里执行的,用到的是axios请求接口,创建有一个action,将获取到的接口数据存进去,发送dispatch方法通知store修改里面的数据
componentDidMount(){
axios.get('/todolist').then((res)=>{
const data = res.data
const action = getInitListAction(data)
// 错误写法
function analyzeReducer(state: TFilterItemVal[], action: TReducerAction<TFilterItemVal>) {
const { index, data, type } =
react-router-cache-route 是路由缓存工具,通常在dva的首页app.js中一起搭配使用
但是需要注意的是,每一个route路由路径在定义的时候,都需要指定是否需要cache,如果使用copy大法,很容易忽略
这会导致一种后果,即从路由A点击跳转进入路由B,再由路由B点击返回路由A,最后再次点击跳转进入路由B,打印后会发现,路由B对应的组件没有被重新加载,这正是因为route.js中的配置,配置成了cache=true
import { Router, Route } from
Redux Toolkit 包含一个名为 `createAsyncThunk` 的工具函数,它可以帮助我们轻松地处理异步请求。
使用 `createAsyncThunk` 函数,我们可以定义一个函数来处理异步请求,并且该函数会自动生成与请求相关的三个 action:pending(请求开始),fulfilled(请求成功)和 rejected(请求失败)。
下面是一个使用 `createAsyncThunk` 的示例:
```javascript
import { createAsyncThunk } from '@reduxjs/toolkit';
import { fetchUser } from './api';
export const getUser = createAsyncThunk(
'user/fetch',
async (userId, thunkAPI) => {
const response = await fetchUser(userId);
return response.data;
// 然后在 reducer 中处理请求状态
const userSlice = createSlice({
name: 'user',
initialState: {
user: null,
isLoading: false,
error: null,
reducers: {},
extraReducers: {
[getUser.pending]: (state, action) => {
state.isLoading = true;
[getUser.fulfilled]: (state, action) => {
state.isLoading = false;
state.user = action.payload;
[getUser.rejected]: (state, action) => {
state.isLoading = false;
state.error = action.error.message;
在上面的示例中,我们首先使用 `createAsyncThunk` 函数创建了一个名为 `getUser` 的异步 action,它的名称为 `user/fetch`。然后我们在 `extraReducers` 中处理了请求状态。当请求开始时,`getUser.pending` action 会被触发,我们可以在这里将 `isLoading` 设置为 `true`。当请求成功时,`getUser.fulfilled` action 会被触发,我们可以在这里将 `isLoading` 设置为 `false` 并将返回的数据保存在 `user` 属性中。当请求失败时,`getUser.rejected` action 会被触发,我们可以在这里将 `isLoading` 设置为 `false` 并将错误信息保存在 `error` 属性中。
注意,我们在异步函数中的第二个参数 `thunkAPI` 中可以访问 `dispatch`、`getState`、`extra` 和 `fulfillWithValue` 等方法,这些方法可以帮助我们更好地处理异步请求。