【问题标题】:mapDispatchToProps dispatch action not working to update StatemapDispatchToProps 调度操作无法更新状态
【发布时间】:2017-12-02 04:30:43
【问题描述】:

在我的 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 被调用时,我可以在这里看到更新的状态。

但是我不想从我的 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:

&lt;li key={ coin.id } onClick={ ()=&gt; this.clickCoin(coin) }&gt;

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

export default connect(null, mapDispatchToProps)(SearchCoin)

这是调用this.props.selectCoin的类方法clickCoin

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 状态没有任何反应。

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
});

【问题讨论】:

  • 您是否尝试过使用来自reduxbindActionCreators?从mapDispatchToProps返回的对象内的selectCoin: bindActionCreators(addCoin, dispatch)

标签: javascript reactjs redux react-redux


【解决方案1】:

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

变化:

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

到:

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

【讨论】:

  • 啊,就是这样!谢谢:D
【解决方案2】:

除了 azium answer,您还可以使用这样的操作。它为您节省了一些写作时间,

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

你可以这样使用它,

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

【讨论】:

  • 不错!很棒的小费和 +1!
  • 这会绑定动作创建者来调度吗?
猜你喜欢
  • 2019-12-04
  • 2020-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-14
  • 1970-01-01
  • 2016-12-18
  • 2019-11-02
相关资源
最近更新 更多