用react-redux和redux-thunk作为装载指示器

amrnrhlw  于 2023-02-19  发布在  React
关注(0)|答案(1)|浏览(161)

我正在做一个使用react-redux和redux-thunk进行开发的项目。以前的方法是逐个检查API调用,然后手动检查是否所有数据都被提取。我发现在v7.0之后,react-redux中引入了batch来帮助解决这个问题。但是页面也需要加载指示符。
目前的方法是在批处理中进行几次调度,以减少不必要的重新渲染,并手动检查是否在渲染中获取了所有数据,但我想知道是否有任何其他方法可以应用于batch,以减少一些硬代码检查。
下面是当前的示例代码:

// in action file
...
function fetchSomeData() {
    // call api to store data
    return dispatch => {
        batch(() => {
            dispatch(fetchData1());
            dispatch(fetchData2());
            dispatch(fetchData3());
            ..some more dispatches...
        });
    }
}
...

// in react component
dataLoaded(){
    ....retrieve all the data from different places... 
    if (!data1)    return false;
    if (!data2)    return false;
    ...check all the data...
    return true;
}

...
render() {
    if (this.dataLoaded()) {
        return actual_content;
    } else {
        return loading_content;
    }
}
...

我尝试直接使用then,并创建另一个方法,返回batch,调用fetchSomeData,然后使用then(),但都产生“无法读取未定义的属性'then'”错误。
我也用过Promise.all,但是没有用,Promise.all的用法如下:

function fetchSomeData() {
    // call api to store data
    return dispatch => {
        Promise.all([
            dispatch(fetchData1());
            dispatch(fetchData2());
            dispatch(fetchData3());
            ..some more dispatches...
        ])
        .then(() => dispatch(setLoading(false)));
    }
}

我还检查了其他帖子的stackoverflow,但许多帖子建议其他中间件,和额外的依赖性需要批准,因为其中一个要求是有限的带宽,使用最小的依赖性需要。

yfjy0ee7

yfjy0ee71#

Redux Toolkit实际上帮助我解决了这个问题。一个示例代码如下所示:

  • 用户切片
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import axios from 'axios';

export const userSlice = createSlice({
  name: 'user',
  initialState: {
    data: [],
    isLoading: false,
    error: null,
  },
  extraReducers(builder) {
    builder.addCase(fetchUsers.pending, (state, action) => {
      state.isLoading = true;
    });
    builder.addCase(fetchUsers.fulfilled, (state, action) => {
      state.isLoading = false;
      state.data = action.payload;
    });
    builder.addCase(fetchUsers.rejected, (state, action) => {
      state.isLoading = false;
      state.error = action.error;
    });
  },
});

export const fetchUsers = createAsyncThunk('users/fetch', async () => {
  const response = await axios.get(
    'https://jsonplaceholder.typicode.com/users'
  );
  console.log(new Date());

  return response.data;
});

export const usersReducer = userSlice.reducer;
  • 切片后
// similar configuration as user
function later(delay) {
  return new Promise(function (resolve) {
    setTimeout(resolve, delay);
  });
}

export const fetchPosts = createAsyncThunk('posts/fetch', async () => {
  await later(5000);

  const response = await axios.get(
    'https://jsonplaceholder.typicode.com/posts'
  );

  console.log(new Date());

  return response.data;
});
  • 第三片叫雷鸣

这个动作不一定是异步thunk,编写一个自定义thunk也可以。

// similar configuration as previous
export const fetchHome = createAsyncThunk(
  'home/fetch',
  async (_, thunkAPI) => {
    const res = await Promise.all([
      thunkAPI.dispatch(fetchUsers()),
      thunkAPI.dispatch(fetchPosts()),
    ]);

    console.log(res);

    return [];
  }
);

结果如下所示:

fetch home thunk等待所有异步thunk解析完毕,然后发出最终结果。
参考:Dispatch action on the createAsyncThunk?

相关问题