【问题标题】:Redux Toolkit createSlice in ReactReact 中的 Redux 工具包 createSlice
【发布时间】:2020-07-30 14:35:10
【问题描述】:

我正在学习 Redux-Saga,一切都适用于 { configureStore, getDefaultMiddleware, createAction, createReducer }。但是,我无法成功实现createSlice

我的操作似乎被派发得很好(尽管我不确定,因为我有多个 Redux 存储并且将 console.log 放在 createSlice 中似乎不起作用......)。我只是无法获得store 值 - 在调度操作之后,相关状态值(最初为'')变为undefined。我确实将我的组件包装在 Provider 和所有内容中。有人能告诉我createSlice 是如何工作的吗?谢谢。

已解决我的代码中的其他地方有一个错误,这就是减速器无法正常工作的原因。但是我问的是什么以及导致我的问题是这样的:传递给createSlice 的操作必须是“纯”函数,意思是:(state, action) -> state,没什么花哨的。这就是为什么我不得不从这个createSlice 中删除我的获取函数(getData1getData2)。

ComponentWrapper 返回这个

<Provider store={toolkitCreateSliceStore}>
    <ReduxToolkitCreateSliceComponent />
</Provider>

组件(按钮只是调度动作)

class ReduxToolkitCreateSliceComponent extends React.Component {

    render () {
        return (
            <>
                <h2>
                    {this.props.data1}
                    {(this.props.data1!=='' && this.props.data2!=='') ? ', ' : ''}
                    {this.props.data2}
                </h2><br/>
                <h3>{this.props.message}</h3>
                <Button1 />
                <Button2 />
                <Button3 />
            </>
        );
    }
}

function mapStateToProps(state) {
    return {
        data1: state.toolkitCreateSliceReducer.data1,
        data2: state.toolkitCreateSliceReducer.data2,
        message: state.toolkitCreateSliceReducer.message
    };
}

export default connect(mapStateToProps)(ReduxToolkitCreateSliceComponent);

Redux 工具包切片

import { createSlice } from "@reduxjs/toolkit";
import axios from "axios";

const initialSliceState = {
    data1: '',
    data2: '',
    message: ''
};

const slice = createSlice({
    name: "slice",
    initialState: initialSliceState,
    reducers: {
        getData1: (state, action) => {
            return dispatch => {
                dispatch(loading1());
                return axios.get('http://localhost:8081/data1')
                    .then(function (response) {
                        if (response.status === 200) {
                            dispatch(setResponse1(response.data));
                        }
                    }).catch(error => dispatch(displayError1(error)));
            };
        },
        getData2: (state, action) => {
            return dispatch => {
                dispatch(loading2());
                return axios.get('http://localhost:8081/data2')
                    .then(function (response) {
                        if (response.status === 200) {
                            dispatch(setResponse2(response.data));
                        }
                    }).catch(error => dispatch(displayError2(error)));
            };
        },
        setResponse1: (state, action) => {
            state.data1 = action.payload;
            state.message = 'success';
        },
        setResponse2: (state, action) => {
            state.data2 = action.payload;
            state.message = 'success';
        },
        reset: (state, action) => {
            state.data1 = '';
            state.data2 = '';
            state.message = 'reset';
        },
        loading1: (state, action) => {
            state.message = 'loading';
        },
        loading2: (state, action) => {
            state.message = 'loading';
        },
        displayError1: (state, action) => {
            state.message = action.payload;;
        },
        displayError2: (state, action) => {
            state.message = action.payload;;
        }
    }
});

export const toolkitCreateSliceReducer = slice.reducer;

const { getData1, getData2, setResponse1, setResponse2, reset, loading1, loading2,
    displayError1, displayError2} = slice.actions;

export default slice;

Redux 工具包商店

const middleware = [
    ...getDefaultMiddleware()
];

const toolkitCreateSliceStore = configureStore({
    reducer: {
        toolkitCreateSliceReducer
    },
    middleware
});

export default toolkitCreateSliceStore;

【问题讨论】:

  • 恐怕问题不清楚。具体是什么不起作用?
  • 你是对的。我只是无法获得 store 值 - 在调度操作之后,相关状态值(最初为 '')变为 undefined

标签: javascript reactjs redux


【解决方案1】:

你的“减速器”大错特错。

reducer 必须绝不有任何副作用,例如 AJAX 调用

你已经编写了一些 Redux “thunk”函数,你的 reducer 应该是:

getData1: (state, action) => {
            return dispatch => {
                dispatch(loading1());
                return axios.get('http://localhost:8081/data1')
                    .then(function (response) {
                        if (response.status === 200) {
                            dispatch(setResponse1(response.data));
                        }
                    }).catch(error => dispatch(displayError1(error)));
            };
        },

这是一个thunk,而不是reducer。

reducer 类似于:

getData(state, action) {
  return action.payload;
}

我特别推荐阅读我们全新的“Redux Essentials”核心文档教程,该教程教初学者“如何以正确的方式使用 Redux”,使用我们最新推荐的工具和实践,如 Redux Toolkit。它具体介绍了 reducer 应该如何工作,如何使用 createSlice 编写 reducer,以及如何在 createSlice 旁边编写和使用 thunk:

https://redux.js.org/tutorials/essentials/part-1-overview-concepts

【讨论】:

    【解决方案2】:

    如果您对创建异步操作感兴趣,让我向您推荐一个我创建并使用的 npm 包。 saga-toolkit 允许异步函数被 sagas 解析。

    slice.js

    import { createSlice } from '@reduxjs/toolkit'
    import { createSagaAction  } from 'saga-toolkit'
    
    const name = 'example'
    
    const initialState = {
      result: null,
      loading: false,
      error: null,
    }
    
    export const fetchThings = createSagaAction(`${name}/fetchThings`)
    
    const slice = createSlice({
      name,
      initialState,
      extraReducers: {
        [fetchThings.pending]: () => ({
          loading: true,
        }),
        [fetchThings.fulfilled]: ({ payload }) => ({
          result: payload,
          loading: false,
        }),
        [fetchThings.rejected]: ({ error }) => ({
          error,
          loading: false,
        }),
      },
    })
    
    export default slice.reducer
    

    sagas.js

    import { call } from 'redux-saga/effects'
    import { takeLatestAsync } from 'saga-toolkit'
    import API from 'hyper-super-api'
    import * as actions from './slice'
    
    function* fetchThings() {
      const result = yield call(() => API.get('/things'))
      return result
    }
    
    export default [
      takeLatestAsync(actions.fetchThings.type, fetchThings),
    ]
    

    【讨论】:

      猜你喜欢
      • 2021-03-11
      • 2021-10-04
      • 2021-01-12
      • 1970-01-01
      • 2022-12-11
      • 2023-02-26
      • 2021-11-01
      • 2022-12-21
      • 1970-01-01
      相关资源
      最近更新 更多