使用 React/Redux saga 将数据从组件传递到 action 和 saga

Posted

技术标签:

【中文标题】使用 React/Redux saga 将数据从组件传递到 action 和 saga【英文标题】:Pass data from component to action and saga using React/Redux saga 【发布时间】:2018-08-04 21:03:09 【问题描述】:

我将 React 与 Redux Saga 一起使用。当我尝试使用 this.props.dispatch(type: CreateActionType.CREATE_ASYNC); 在我的组件中执行传奇效果时什么都没有发生,它没有被执行。

当我在 index.js 中 console.log this.props.data 时,它是空的

如果此处缺少必要信息,请告诉我。

api.js

export const create = (params) => 
const dataList = 
    data: data1: 1, data2: 2,,
    statusCode: 200,

    return dataList;
;

sagas.js

import  put, call, takeEvery , all  from 'redux-saga/effects'
import  create  from '../api';

import * as CreateActionType from './constants';

export function* createAsync(action) 
    const result = yield call(create, action.params);
    const statusCode = result.statusCode;

    if (statusCode === 200) 
        yield [
            put( type: CreateActionType.CREATE_SUCCESS, params: result.data ),
        ];
     else 
        console.warn("createAsync error", result.data);
    
;

function* WatchCreate()  
    yield [
        takeEvery(CreateActionType.CREATE_ASYNC, createAsync),
    ]  


export default function* rootSaga() 
    yield all([
        WatchCreate(),
    ])

store.js

import * as CreateActionType from './constants';
import  combineReducers  from 'redux';

const defaultState = 
    data: null,


function CreateStore(state = defaultState, action) 

    switch (action.type) 
        case CreateActionType.CREATE_SUCCESS:
            return 
                ...state,
                createStatus: true,
            ;
        default:
            return state;
    
;

const rootReducer = combineReducers(
    CreateStore,
)

export default rootReducer;

index.js

import React,  Component  from 'react';
import  connect  from 'react-redux';
import * as CreateActionType from './constants';

class CreateNote extends Component 
    constructor(props)
        super(props);

        this.state = ;
    ;

    componentDidMount() 
        this.props.dispatch(
            type: CreateActionType.CREATE_ASYNC,
        );
    ;

    render() 
        return <p>this.props.data</p>;
    


const mapStateToProps = (state) =>         
    return state.CreateStore;
;

export default connect(mapStateToProps)(CreateNote);

configstore.js

import  createStore, applyMiddleware  from 'redux';
import createSagaMiddleware from 'redux-saga';
import rootSaga from './container/sagas';
import rootReducer from './container/stores';

export default function ConfigureStore() 
    const sagaMiddleware = createSagaMiddleware();

    const store = createStore(rootReducer,
        applyMiddleware(sagaMiddleware)
    );

    sagaMiddleware.run(rootSaga);

    return store;

【问题讨论】:

创建代码sn-p并分享,你会得到更多反馈 这是基本的 redux 传奇 你应该调试它。如果控制台中没有错误消息,请添加一些 console.log 调用以查看执行与否。 您越容易为他人提供帮助,就越有可能帮助您。 【参考方案1】:

很难判断出了什么问题,因为代码非常多。

假设 saga 实际正在运行,您永远不会对返回的数据做任何事情,这就解释了为什么 this.props.data 为空。你可以试试这个。

 case CreateActionType.CREATE_SUCCESS:
        return 
            ...state,
            createStatus: true,
            data: action.params.data,
        ;

如果您不确定 sagas 是否正在运行,您应该在 api.js 和 sagas.js 中添加一些日志调用。

我看不出 sagas 不起作用的任何原因,但您可以尝试进一步简化它。我认为产生效果数组与产生单一效果相比没有任何好处。

export default function* rootSaga() 
    yield takeEvery(CreateActionType.CREATE_ASYNC, createAsync)

【讨论】:

@Lid 我有来自 api.js 的数据,我用 componentWillReceiveProps(nextProps) this.setState(content: nextProps.data); 固定在 index.js 。谢谢。 为什么要为此使用组件状态?您正在使用 redux。在 redux 中保持状态并在组件中使用 props 要简单得多。【参考方案2】:

试着简化一下

function* WatchCreate()  
    yield [
        takeEvery(CreateActionType.CREATE_ASYNC, createAsync),
    ]  


export default function* rootSaga() 
    yield all([
        WatchCreate(),
    ])

export default function* rootSaga() 
    yield all([
        takeEvery(CreateActionType.CREATE_ASYNC, createAsync),
    ])

我发现尽可能多地处理效果级别(同步创建的对象)而不是嵌套的 sagas 更容易。 您的问题可能是您调用WatchCreate 并尝试使用返回值,尽管它没有。

【讨论】:

@NguyễnThànhNam Mh。我注意到您还将put 放在一个数组中,这是不必要的。所以你是说你的状态仍然有 null ?你检查过你所有的 sagas 都被断点/调试器调用了吗?您是否在开发工具中看到所有预期的操作?【参考方案3】:

你的动作传奇有一个论点createAsync(action)。调用函数时需要传递数据,例如takeEvery(createActionType.CREATE_ASYNC, createAsync, action)。以下面这个例子为例。

import  call, put, SagaReturnType, takeLatest  from '@redux-saga/core/effects'
import axios,  AxiosResponse  from 'axios'
import * as ActionCreators from './actionCreators'
import * as ActionTypes from './actionTypes'

type apiResponse = SagaReturnType<typeof deleteUser>

const deleteUser = async (userId: string): Promise<AxiosResponse> => 
    return axios.delete(`localhost:8081/users/$userId`)


function* deleteUserSaga(user: User) 
    try 
        if (user.userId) 
            const response: apiResponse = yield call(deleteUser, user.userId)

            if (response.status === 200) 
                put(ActionCreators.deleteSuccess(user))
            

            throw new Error('User delete unsuccessful')
        
     catch (err) 
        put(ActionCreators.deleteError(err))
    


// eslint-disable-next-line
export default function* DeleteUserWatcher(user: User) 
    yield takeLatest(ActionTypes.DELETE_BEGIN, deleteUserSaga, user)

【讨论】:

以上是关于使用 React/Redux saga 将数据从组件传递到 action 和 saga的主要内容,如果未能解决你的问题,请参考以下文章

React redux saga - 出现一些奇怪的行为

访问 saga 中的 store.dispatch 以与 react router redux 一起使用

react / redux / sagas - 如何基于现有商店数据链接动作?

react + redux + saga +服务器端渲染+如何停止服务器端渲染页面的额外ajax调用?

从 Redux-Saga 函数更新另一个 Redux 存储的最佳方法

electron+react-redux-saga基础项目配置