mapDispatchToProps调度操作无法更新状态

时间:2017-06-28 17:09:06

标签: javascript reactjs redux react-redux

在我的 index.js 中,addCoin操作有效。

import { addCoin } from './reducer/portfolio/actions'

const element = document.getElementById('coinhover');

const store = createStore(reducer, compose(
    applyMiddleware(thunk),
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
));

store.dispatch(addCoin('bitcoin'));

调用store.dispatch时,我可以在此处看到更新后的状态。 enter image description here

但是我不想从我的index.js调用调度操作,而是从我的组件中调用。

我的SearchCoin组件:

import React from 'react'
import { connect } from 'react-redux'
import * as R from 'ramda'
import * as api from '../../services/api'
import { addToPortfolio, findCoins } from '../../services/coinFactory'
import { addCoin } from '../../reducer/portfolio/actions'

const mapDispatchToProps = (dispatch) => ({
    selectCoin(coin) {
        return () => {
            dispatch(addCoin(coin))
        }
    }
});

class SearchCoin extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            searched: []
        };
        // console.log('props', props);
        this.close = this.close.bind(this);
    }

    componentDidMount() {
        this.coinInput.focus(); 
        this.handleChange = this.handleChange.bind(this);
        this.clickCoin = this.clickCoin.bind(this);
    }

    handleChange() {
        const text = document.getElementById('coin-search').value;
        const search = (text)  => this.setState({ searched: findCoins(text) });
        const clearSearch = () => this.setState({ searched: [] });
        text.length > 1 ? search(text) : clearSearch();
    }

    clickCoin(coin) {
        console.log('clickCoin', coin);
        // api.getCoin(coin.id).then((res) => {
        //  const apiCoin = R.head(res.data);
        //  addToPortfolio(apiCoin);
        // });
        this.props.selectCoin(coin);
        this.props.closeSearch();
    }

    close() {
        this.props.closeSearch();
    }

    render() {
        const searched = this.state.searched.map((coin) => {
            return (
                <li key={ coin.id } onClick={ ()=> this.clickCoin(coin) }>
                    <div className="coin-logo">
                        <img src={ coin.logo }/>
                    </div>
                    <span>{ coin.name }</span>
                </li>
            );
        });

        return (
            <div id="search-coin-component">
                <input type="text"
                       id="coin-search"
                       className="coin-search-input fl"
                       placeholder="Search"
                       onChange={ ()=> this.handleChange() }
                       ref={ (input) => { this.coinInput = input; } } />
                <div className="icon-cancel-outline fl" onClick={ this.close }></div>
                <div className="coin-select">
                    <ul>
                        { searched }
                    </ul>
                </div>
            </div>
        )
    }
}

export default connect(null, mapDispatchToProps)(SearchCoin)

这是onClick:

<li key={ coin.id } onClick={ ()=> this.clickCoin(coin) }>

在文件的底部,我使用connect来添加mapDispatchToProps

export default connect(null, mapDispatchToProps)(SearchCoin)

以下是调用clickCoin

的类方法this.props.selectCoin
clickCoin(coin) {
    console.log('clickCoin', coin);
    this.props.selectCoin(coin);
    this.props.closeSearch();
}

最后selectCoin

import { addCoin } from '../../reducer/portfolio/actions'

const mapDispatchToProps = (dispatch) => ({
    selectCoin(coin) {
        return () => {
            dispatch(addCoin(coin))
        }
    }
});

然而,当我单击按钮时,似乎没有触发调度,因为redux状态没有任何反应。enter image description here

import * as R from 'ramda'
import * as api from '../../services/api'
import { addToPortfolio } from '../../services/coinFactory'

export const ADD_COIN = 'ADD_COIN'

export function addCoin(coin) {
    console.log('addCoin', coin);
    return dispatch =>
        api.getCoin(coin)
            .then((res) => addToPortfolio(R.head(res.data)))
            .then((portfolio) => dispatch(add(portfolio)));
}

// action creator
export function add(portfolio) {
    return {
        type: ADD_COIN,
        portfolio
    }
}

减速机

import { ADD_COIN } from './actions'

const initialState = [];

export default (state = initialState, action) => {
    switch(action.type) {
        case ADD_COIN:
            return action.portfolio;
        default:
            return state;
    }
}

reducer / index.js

import { combineReducers } from 'redux'
import portfolio from './portfolio'

export default combineReducers({
    portfolio
});

2 个答案:

答案 0 :(得分:5)

除了azium答案,你可以使用这样的动作。它为您节省了一些文字,

export default connect(null, {addCoin})(SearchCoin)

你可以像这样使用它,

clickCoin(coin) {
    console.log('clickCoin', coin);
    this.props.addCoin(coin);
    this.props.closeSearch();
}

答案 1 :(得分:3)

问题是你用一个额外的函数包装你的函数。

变化:

const mapDispatchToProps = (dispatch) => ({
  selectCoin(coin) {
    return () => { <--- returning extra function
      dispatch(addCoin(coin))
    }
  }
})

为:

const mapDispatchToProps = (dispatch) => ({
  selectCoin(coin) { dispatch(addCoin(coin)) }
})