简体   繁体   English

React-Redux:如何将Reducer与Thunk中间件结合

[英]React-Redux : How to combine reducers with Thunk middleware

I started coding a web interface to manage my server's files using React/Redux. 我开始编写一个Web界面代码,以使用React / Redux管理服务器文件。
I now have a page which requests my API to get files list as JSON. 现在,我有一个页面,请求我的API以JSON格式获取文件列表。

It works well so I added another reducer and an action button to simply display the filename on click. 它运行良好,因此我添加了另一个reducer和一个操作按钮,以在单击时简单地显示文件名。
But combining my datalist-reducer with the active-file reducer doesn't work. 但是,将我的datalist-reduceractive-file reducer结合起来是行不通的。
The files list creation process fails with the following error: 文件列表创建过程失败,并出现以下错误:

TypeError: Undefined is not a function (near'...this.props.datalist.map...') TypeError:未定义不是函数(在'... this.props.datalist.map ...'附近)

Thank you. 谢谢。

Here's my code : 这是我的代码:

index.js index.js

import React from 'react';
import ReactDOM from 'react-dom';
import {createStore, applyMiddleware, combineReducers} from 'redux';
import {Provider, connect} from 'react-redux';
import thunk from 'redux-thunk';
import activeFileReducer from './reducers/reducer-active-file';
import dataListReducer from './reducers/reducer-data';

const reducer = combineReducers({
    datalist: datalist, 
    activefile: activefile
})
const createStoreWithMiddleware = applyMiddleware(thunk)(createStore)
let store = createStoreWithMiddleware(reducer);
ReactDOM.render(<Provider store={store}>
    <App />
    </Provider>, document.getElementById('table'));

datalist-reducer 数据表减少器

export default function datalist (state = {}, action) {
    switch (action.type) {
        case "FETCH_REQUEST":
            return state;
        case "FETCH_SUCCESS": 
            return {datalist: action.payload};
        default:
            return state;
    }
}

active-file-reducer 主动文件减少器

export default function activefile (state= {}, action){
        switch(action.type){
            case "FILE_SELECTED":
                return action.payload;
            default:
                return state;
        }

    }

actions/index.js 动作/ index.js

export const selectFile = (file) => {
    return {
        type: "FILE_SELECTED",
        payload: file
    }
}


export const fetchDataRequest = () =>{
    return {
      type: "FETCH_REQUEST"
    }
}

export const fetchDataSuccess = (payload) => {
    return {
        type: "FETCH_SUCCESS",
        payload
    }
}

export const fetchDataError = () => {
    return {
        type: "FETCH_ERROR"
    }
}

data-list-container 数据列表容器

import React, {Component} from 'react';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {fetchDataRequest, fetchDataSuccess, fetchDataError, selectFile} from '../actions/index';

class DataList extends Component{
    componentDidMount(){
        this.props.fetchDataWithRedux()

    }

    render(){
        return(
            <ul>
                {
                    this.props.datalist && 
                    this.props.datalist.map((item, key) =>{
                        return(
                            <li key={key} onClick={() => this.props.selectFile(item.title)}>{item.title}</li>
                        )
                    })
                }
            </ul>
        )       
    }
}


function fetchDataWithRedux() {
    return (dispatch) => {
        dispatch(fetchDataRequest());
        return fetchData().then(([response, json]) =>{
            console.log(response);
            if(response.status === 200){
            dispatch(fetchDataSuccess(json))
            dispatch(selectFile())
    }
    else{
        dispatch(fetchDataError())
        dispatch(selectFile())
    }
    })
}
}

function fetchData() {
const URL = "http://localhost:5000/api/deposit/view";
return fetch(URL, { method: 'GET'})
    .then( response => Promise.all([response, response.json()]));
}

function mapStateToProps(state){
    return {
        datalist: state.datalist
    }
}

export default connect(mapStateToProps, {fetchDataWithRedux})(DataList);

Try changing your index.js file to something like: 尝试将index.js文件更改为以下内容:

 import { createStore, applyMiddleware, combineReducers } from 'redux'; import thunk from 'redux-thunk'; import { Provider } from 'react-redux'; import ReactDOM from 'react-dom'; import App from './App'; const reducer = combineReducers({ datalist: datalist, activefile: activefile }); // Note: this API requires redux@>=3.1.0 const store = createStore( reducer, applyMiddleware(thunk) ); ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('table') ); 

NB: Added in missing imports (some guessed) for completeness. 注意:为完整性起见,添加了缺失的进口(有人猜测)。

Edit: Now that your reducers are combined, you need to amend your datalist reducer: 编辑:现在您的化简器已经合并,您需要修改datalist器:

 // datalist-reducer export default function datalist (state = [], action) { switch (action.type) { case "FETCH_REQUEST": return state; case "FETCH_SUCCESS": return action.payload || []; default: return state; } } 

This is because, your datalist reducer will be given the datalist key from your store, and your state will be the contents of that key (or undefined on the first run). 这是因为,将为您的datalist提供商店中的datalist键,并且您的state将是该键的内容(或在第一次运行时未定义)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM