Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

createAsyncThunk创建的action无法使用dispatch #15517

Open
hikzhang opened this issue Apr 16, 2024 · 12 comments
Open

createAsyncThunk创建的action无法使用dispatch #15517

hikzhang opened this issue Apr 16, 2024 · 12 comments
Labels
F-react Framework - React T-weapp Target - 编译到微信小程序 V-3 Version - 3.x

Comments

@hikzhang
Copy link

相关平台

微信小程序

小程序基础库: 3.4.1
使用框架: React

复现步骤

  1. 在slice中定义foo = createAsyncThunk(...),并在createSlice的extrareducers中使用build.addCase(foo.pending...)等
  2. 在页面中使用dispatch(foo)

期望结果

foo定义的async functionf

实际结果

执行时报错:AbortController is not defined

ReferenceError: AbortController is not defined
    at vendors-node_modules_taro_weapp_prebundle_reduxjs_toolkit_js.js?t=wechat&s=1713083731279&v=c3009756f740784f3e1fbc8afa686d9b:2359
    at vendors-node_modules_taro_weapp_prebundle_reduxjs_toolkit_js.js?t=wechat&s=1713083731279&v=c3009756f740784f3e1fbc8afa686d9b:1525
    at vendors-node_modules_taro_weapp_prebundle_reduxjs_toolkit_js.js?t=wechat&s=1713083731279&v=c3009756f740784f3e1fbc8afa686d9b:1790
    at vendors-node_modules_taro_weapp_prebundle_reduxjs_toolkit_js.js?t=wechat&s=1713083731279&v=c3009756f740784f3e1fbc8afa686d9b:1614
    at Object.current (index.tsx?cf8d:13)
    at Object.callback (vendors-node_modules_taro_weapp_prebundle_tarojs_plugin-framework-react_dist_runtime_js.js?t=wechat&s=1713083731279&v=dc9330fe3530ade2dc87a23f82bc3b47:96)
    at vendors-node_modules_taro_weapp_prebundle_chunk-H5CKLZB7_js.js?t=wechat&s=1713083731279&v=1f79f6e1c526573bda1897e0aa961ea9:1131
    at Array.map (<anonymous>)
    at safeExecute (vendors-node_modules_taro_weapp_prebundle_chunk-H5CKLZB7_js.js?t=wechat&s=1713083731279&v=1f79f6e1c526573bda1897e0aa961ea9:1131)
    at AppWrapper.<anonymous> (vendors-node_modules_taro_weapp_prebundle_chunk-H5CKLZB7_js.js?t=wechat&s=1713083731279&v=1f79f6e1c526573bda1897e0aa961ea9:1209)(env: macOS,mp,1.06.2402040; lib: 3.4.1)

环境信息

taro info
👽 Taro v3.6.26

(node:65681) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)

  Taro CLI 3.6.26 environment info:
    System:
      OS: macOS 14.4.1
      Shell: 5.9 - /bin/zsh
    Binaries:
      Node: 21.7.2 - /opt/homebrew/bin/node
      npm: 10.5.0 - /opt/homebrew/bin/npm
    npmPackages:
      @tarojs/cli: 3.6.26 => 3.6.26
      @tarojs/components: 3.6.26 => 3.6.26
      @tarojs/helper: 3.6.26 => 3.6.26
      @tarojs/plugin-framework-react: 3.6.26 => 3.6.26
      @tarojs/plugin-platform-alipay: 3.6.26 => 3.6.26
      @tarojs/plugin-platform-h5: 3.6.26 => 3.6.26
      @tarojs/plugin-platform-jd: 3.6.26 => 3.6.26
      @tarojs/plugin-platform-qq: 3.6.26 => 3.6.26
      @tarojs/plugin-platform-swan: 3.6.26 => 3.6.26
      @tarojs/plugin-platform-tt: 3.6.26 => 3.6.26
      @tarojs/plugin-platform-weapp: 3.6.26 => 3.6.26
      @tarojs/react: 3.6.26 => 3.6.26
      @tarojs/runtime: 3.6.26 => 3.6.26
      @tarojs/shared: 3.6.26 => 3.6.26
      @tarojs/taro: 3.6.26 => 3.6.26
      @tarojs/taro-loader: 3.6.26 => 3.6.26
      @tarojs/webpack5-runner: 3.6.26 => 3.6.26
      babel-preset-taro: 3.6.26 => 3.6.26
      eslint-config-taro: 3.6.26 => 3.6.26
      react: ^18.0.0 => 18.2.0

补充信息

实际taro版本是3.6.26(无可选项)

@taro-bot2 taro-bot2 bot added F-react Framework - React T-weapp Target - 编译到微信小程序 V-3 Version - 3.x labels Apr 16, 2024
This was referenced Apr 20, 2024
@seekerliu
Copy link

解决方法:
1,安装这俩包:yet-another-abortcontroller-polyfill,event-target-polyfill
2,app.js import:
import 'event-target-polyfill';
import 'yet-another-abortcontroller-polyfill';

@hikzhang
Copy link
Author

感谢!按你的解决方法成功运行了。

不过是否应该从Taro框架本身引入才更好呢。

@hikzhang
Copy link
Author

hikzhang commented May 9, 2024 via email

@mrold
Copy link

mrold commented May 17, 2024

@hikzhang 我遇到的问题是,模拟器正常,真机调试dispatch之后action没有执行。我的是抖音小程序。

@mrold
Copy link

mrold commented May 17, 2024

装了以后直接白屏了

解决方法: 1,安装这俩包:yet-another-abortcontroller-polyfill,event-target-polyfill 2,app.js import: import 'event-target-polyfill'; import 'yet-another-abortcontroller-polyfill';

@hikzhang
Copy link
Author

hikzhang commented May 17, 2024 via email

@luankefei
Copy link

遇到了同样的问题,感谢 @seekerliu

@moxiaonai
Copy link

装了以后直接白屏了

解决方法: 1,安装这俩包:yet-another-abortcontroller-polyfill,event-target-polyfill 2,app.js import: import 'event-target-polyfill'; import 'yet-another-abortcontroller-polyfill';

解决了吗,我也是装完白屏

@mrold
Copy link

mrold commented Jul 19, 2024

装了以后直接白屏了

解决方法: 1,安装这俩包:yet-another-abortcontroller-polyfill,event-target-polyfill 2,app.js import: import 'event-target-polyfill'; import 'yet-another-abortcontroller-polyfill';

解决了吗,我也是装完白屏

我放弃了,移除了redux

@moxiaonai
Copy link

moxiaonai commented Jul 23, 2024

装了以后直接白屏了

解决方法: 1,安装这俩包:yet-another-abortcontroller-polyfill,event-target-polyfill 2,app.js import: import 'event-target-polyfill'; import 'yet-another-abortcontroller-polyfill';

解决了吗,我也是装完白屏

我放弃了,移除了redux

我这边解决了,后面遇到的同学可以参考,微信小程序应该是可以通过上述的polyfill方案解决
抖音小程序因为限制了globalThis和window的访问,pollyfill不行,引入那两个包以后会白屏,通过分析可以知道这个报错的主要原因是createAsyncThunk里面维护的promise abort状态导致的,可以通过绕过createAsyncThunk来解决,比如:

  1. 手动维护请求的状态
  2. 或者用redux-thunk之类的库去维护异步请求状态就可以避免了
    参考:
import { createSlice } from '@reduxjs/toolkit';
import axios from 'axios';

const initialState = {
  data: null,
  loading: false,
  error: null,
  // 添加一个额外的字段
  userId: null, // 假设我们需要使用这个字段来决定是否请求数据
};

const mySlice = createSlice({
  name: 'mySlice',
  initialState,
  reducers: {
    fetchStart: (state) => {
      state.loading = true;
      state.error = null;
    },
    fetchSuccess: (state, action) => {
      state.loading = false;
      state.data = action.payload;
    },
    fetchError: (state, action) => {
      state.loading = false;
      state.error = action.payload;
    },
    setUserId: (state, action) => {
      state.userId = action.payload;
    },
  },
});

export const { fetchStart, fetchSuccess, fetchError, setUserId } = mySlice.actions;

// 修改后的 fetchData,读取 state
export const fetchData = () => async (dispatch, getState) => {
  const state = getState(); // 读取当前 state
  const { userId } = state.mySlice; // 从 state 中获取 userId
  
  // 如果 userId 不存在或无效,则不进行请求
  if (!userId) {
    console.warn('User ID is required for this request');
    return;
  }

  dispatch(fetchStart()); // 请求开始,设置 loading 为 true
  try {
    const response = await axios.get(`https://api.example.com/data/${userId}`); // 使用 state 中的 userId
    dispatch(fetchSuccess(response.data)); // 请求成功,设置 data 和 loading 状态
  } catch (error) {
    dispatch(fetchError(error.toString())); // 请求失败,设置 error 和 loading 状态
  }
};

export default mySlice.reducer;

@hengkx
Copy link
Contributor

hengkx commented Jul 27, 2024

现在好多库都有依赖AbortController 上面的方法尝试过无效,官方有什么更好的方案吗?

@chaoqiwu
Copy link

chaoqiwu commented Oct 9, 2024

装了以后直接白屏了

解决方法: 1,安装这俩包:yet-another-abortcontroller-polyfill,event-target-polyfill 2,app.js import: import 'event-target-polyfill'; import 'yet-another-abortcontroller-polyfill';

解决了吗,我也是装完白屏

我放弃了,移除了redux

我这边解决了,后面遇到的同学可以参考,微信小程序应该是可以通过上述的polyfill方案解决 抖音小程序因为限制了globalThis和window的访问,pollyfill不行,引入那两个包以后会白屏,通过分析可以知道这个报错的主要原因是createAsyncThunk里面维护的promise abort状态导致的,可以通过绕过createAsyncThunk来解决,比如:

1. 手动维护请求的状态

2. 或者用redux-thunk之类的库去维护异步请求状态就可以避免了
   参考:
import { createSlice } from '@reduxjs/toolkit';
import axios from 'axios';

const initialState = {
  data: null,
  loading: false,
  error: null,
  // 添加一个额外的字段
  userId: null, // 假设我们需要使用这个字段来决定是否请求数据
};

const mySlice = createSlice({
  name: 'mySlice',
  initialState,
  reducers: {
    fetchStart: (state) => {
      state.loading = true;
      state.error = null;
    },
    fetchSuccess: (state, action) => {
      state.loading = false;
      state.data = action.payload;
    },
    fetchError: (state, action) => {
      state.loading = false;
      state.error = action.payload;
    },
    setUserId: (state, action) => {
      state.userId = action.payload;
    },
  },
});

export const { fetchStart, fetchSuccess, fetchError, setUserId } = mySlice.actions;

// 修改后的 fetchData,读取 state
export const fetchData = () => async (dispatch, getState) => {
  const state = getState(); // 读取当前 state
  const { userId } = state.mySlice; // 从 state 中获取 userId
  
  // 如果 userId 不存在或无效,则不进行请求
  if (!userId) {
    console.warn('User ID is required for this request');
    return;
  }

  dispatch(fetchStart()); // 请求开始,设置 loading 为 true
  try {
    const response = await axios.get(`https://api.example.com/data/${userId}`); // 使用 state 中的 userId
    dispatch(fetchSuccess(response.data)); // 请求成功,设置 data 和 loading 状态
  } catch (error) {
    dispatch(fetchError(error.toString())); // 请求失败,设置 error 和 loading 状态
  }
};

export default mySlice.reducer;

Great, this solved my problem. Inspired by you, I listed out my code.

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

const countSlice = createSlice({
  name: 'count',
  initialState: 0,
  reducers: {
    increment(state, action) {
      return state + action.payload;
    },
    decrement(state, action) {
      return state - action.payload;
    },
  },
});

export const { increment, decrement } = countSlice.actions;

export default countSlice.reducer;


// mock time delay
export const delay = (sec) => {
  return new Promise(resolve => setTimeout(resolve, sec * 1000));
}


// Async action creator
export const asyncIncrement = (val) => async dispatch => {
  console.log('asyncIncrement start');
  await delay(2);
  dispatch(increment(val));
  console.log('asyncIncrement end');
};


// dispatch

  const handleAsync = () => {
    dispatch(asyncIncrement(3))
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
F-react Framework - React T-weapp Target - 编译到微信小程序 V-3 Version - 3.x
Projects
Status: Todo
Development

No branches or pull requests

7 participants