【问题标题】:redux saga, issue wit Connect()redux 传奇,Connect() 问题
【发布时间】:2017-10-08 13:46:31
【问题描述】:

我正在尝试使用 redux-saga 从我的 API 中获取一些数据。不幸的是,它失败了,我收到了Uncaught TypeError: this.props.fetchData is not a functionthis.props.someInfo 也未定义。因为我正在制作一些控制台日志,所以我看到没有输入函数getData。我相信这意味着触发动作存在问题。不幸的是,我不知道可能出了什么问题或如何解决它。

createStore.js

import {createStore, applyMiddleware, compose} from 'redux';
import createSageMiddleware from 'redux-saga';

import rootReducer from '../reducers/index';
import rootSaga from './rootSaga';
// import {rootSaga} from '../sagas/FAQSaga';

const sagaMiddleware = createSageMiddleware();

export default function configureStore(initialState) {
    const middleware = applyMiddleware(sagaMiddleware);
    const store = createStore(
        rootReducer,
        compose (
            middleware,
            window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() // for displaying in google dev tools
        )
    );

    sagaMiddleware.run(rootSaga);

    return store;
};

rootSaga.js

import { fork } from 'redux-saga/effects';
import FAQSaga from '../sagas/FAQSaga.js';

export default function * rootSaga() {
    yield [
        fork(FAQSaga)
    ];
}

FAQSaga.js

import * as actions from '../actions/FAQActions';
import axios from 'axios';
import { call, put, take, fork } from 'redux-saga/effects';

export function* getData() {
    try {
        console.log('getdata');
        const response = yield call(axios.get, 'http://localhost:8080/rest/book/all');
        const data = yield response.json();
        yield put(actions.GET_FAQ.SUCCESS(data));
    } catch (e) {
        console.log('erorr');
        console.log(e);
        yield put(actions.GET_FAQ.FAILURE(e));
    }
}

export function* watchData() {
    console.log('watchData');
    while (true) {
        console.log('true');
        yield take(actions.GET_FAQ.REQUEST);
        yield fork(getData);
    }
    // yield takeEvery(actions.GET_FAQ.REQUEST, getData);
}

function * FAQSaga() {
    console.log('FAQSaga');
    yield [
        fork(watchData)
    ];
}

export default FAQSaga;

FAQActions.js

import {REQUEST, SUCCESS, FAILURE, action} from './helpers';

const GET_FAQ_BASE = 'GET_FAQ_';
export const GET_FAQ = {
    REQUEST: GET_FAQ_BASE + REQUEST,
    SUCCESS: GET_FAQ_BASE + SUCCESS,
    FAILURE: GET_FAQ_BASE + FAILURE
};

const POST_FAQ_BASE = 'POST_FAQ_';
export const POST_FAQ = {
    REQUEST: POST_FAQ_BASE + REQUEST,
    SUCCESS: POST_FAQ_BASE + SUCCESS,
    FAILURE: POST_FAQ_BASE + FAILURE
};

export const getFAQ = {
    request: () => action(GET_FAQ.REQUEST),
    success: response => action(GET_FAQ.SUCCESS, {response}),
    failure: error => action(GET_FAQ.FAILURE, {error})
};

export const postFAQ = {
    request: data => action(POST_FAQ.REQUEST, {data}),
    success: response => action(POST_FAQ.SUCCESS, {response}),
    failure: error => action(POST_FAQ.FAILURE, {error})
};

FAQContainer.js

import React from 'react';

import { connect } from 'react-redux'
import * as actions from '../../actions/FAQActions';

import FAQ from './FAQ';

function mapDispatchToProps(dispatch) {
    return ({
        fetchData: () => {dispatch(actions.getFAQ.request)}
    })
}

function mapStateToProps(state) {
    return ({ someInfo: "some info" + state})
}

export default connect(mapStateToProps, mapDispatchToProps)(FAQ);

FAQ.js

import React, {Component} from 'react';
import axios from 'axios';

// import { connect } from 'react-redux'
// import * as actions from '../../actions/FAQActions';


class FAQ extends Component {
    componentDidMount() {
        console.log('this.props.someInfo');
        console.log(this.props.someInfo);
        console.log('this.props.fetchData()');
        console.log(this.props.fetchData())
    }

    render() {
        return (
            <div>
                <p>Here some Frequently Asked Questions will be displayed.</p>
                {console.log('FAQ')}
                { this.props.children }
                <button type="button" onClick={this.postLoginData}>
                    post
                </button>
            </div>
        )
    }
}

FAQ.propTypes = {};

export default FAQ;

【问题讨论】:

  • 您确定在某些父组件中使用的是FAQContainer 而不是FAQ

标签: reactjs redux react-redux redux-saga


【解决方案1】:

在 FAQContainer.js 中尝试使用此代码

function mapDispatchToProps(dispatch) {
    return {
        fetchData() {
            dispatch(actions.getFAQ.request);
        }
    };
}

function mapStateToProps(state) {
    return (state) => ({
        someInfo: "some info" + state;
    });
}

【讨论】:

  • 不幸的是它没有帮助。您可能还有其他建议吗?
【解决方案2】:

您可以简单地将 dispatch 映射到您的 props 并直接从您的组件调度您需要的任何操作,而不是在 props 中创建函数:

function mapDispatchToProps(dispatch) {
  return {
    dispatch
  };
}

现在在你的组件中你可以简单地做:

componentDidMount() {
  this.props.dispatch(actions.getFAQ.request);
}

由于调度只是为了触发一个动作并启动 redux 数据流,我不确定你为什么在调度调用的输出上调用console.log。您无法以同步方式获取异步 API 调用的结果,在将组件连接到 redux 时,应使用 mapStateToProps 进行映射。

我认为会有所帮助的另一个解决方案是使用来自 redux 的 bindActionCreators

import { bindActionCreators } from 'redux';
import * as actionCreators from '../actions/youractions';

//...

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(actionCreators, dispatch),
    dispatch,
  };
}

将动作映射到您的道具中。使用此解决方案,您将不需要手动操作 dispatch,它们将全部自动映射到您的道具。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-28
    • 2019-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-28
    • 1970-01-01
    相关资源
    最近更新 更多