繁体   English   中英

反应redux将状态传递给孩子

[英]React redux pass state down to children

我从React / Redux开始,我有一个类似于Filter子组件包装器的组件。 这个过滤器组件具有自己的状态,我想传递给它的子元素。

export class Filter extends React.Component {
    static propTypes = {
        children: PropTypes.node
    };

    render() {
        return <div>{this.props.children}</div>
    }
}


const mapStateToProps = function( state ) {
    return state.filter;
};

export default connect( (mapStateToProps), {
    doFilter: ( event ) => {
        return console.log(event.target.value);
    }
} )( Filter )

子级之一应该在值更改时调用doFilter

import Filter from 'components/filter';
....

export class CountryFilter extends React.Component {
    render() {
        return (
            <Filter>
                <SelectField floatingLabelText="Country" value='all' fullWidth={true} onChange={this.props.doFilter}>
                    <MenuItem value='all' primaryText="All"/>
                    <MenuItem value='de' primaryText="Germany"/>
                    <MenuItem value='us' primaryText="United States"/>
                </SelectField>
            </Filter>
        );
    }
}

问题在于从未调用过doFilter 如果我在CountryFilter组件中对此this.props进行日志记录,它将返回一个空对象。

难道我做错了什么?

似乎connect()的第二个参数是一个对象,而不是一个函数,该函数又接受dispatch作为参数。 这是文档中提到mapDispatchToProps 现在mapDispatchToProps可以接受一个对象(我相信其中的功能必须是名副其实的Redux动作创建者),但是我通常看到它是通过以下结构完成的:

const mapDispatchToProps = (dispatch) => {
   return {
      foo: () => dispatch(<action>)
   }
}

另外,由于我们将dispatch绑定到props ,所以我们很可能想在此处发出与登录到控制台相反的操作,但是我怀疑这样做只是出于调试目的。

const mapStateToProps = (state) => {
    return {
        filter: state.filter
    }
};

const mapDispatchToProps = (dispatch) => {
    return {
        doFilter: (event) => (
           dispatch({
              type: 'SET_FILTER_VALUE',
              value: event.target.value
           })
        )
    }
};

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

另外,除了发出简单的对象文字(即{type: 'SET_FILTER_VALUE', value: event.target.value ),我们可能还想以动作创建者的形式定义该动作,例如:

actions.js

const SET_FILTER_VALUE = 'SET_FILTER_VALUE';
const setFilterValue = (value) => {
   return {
      type: SET_FILTER_VALUE,
      value
   }
}

Filter.jsx

import { setFilterValue } from '../redux/actions';

...     

const mapDispatchToProps = (dispatch) => {
    return {
        doFilter: (event) => (
           dispatch(
              setFilterValue(event.target.value)
           )
        )
    }
};

...

编辑1

嗯,似乎我们也没有将道具从Filter传递给它的孩子,因此doFilter / setFilterValue将是未定义的。 我们将使用以下惯用语来确保doFilter被传递。 从这里,我们可以将任何希望的东西传递给任何孩子:

过滤

render() {
    const doFilter = this.props.doFilter;
    return (
        <div>
            {
                React.Children.map(this.props.children, function(child) {
                    return React.cloneElement(
                        child, 
                        { doFilter: doFilter }
                    );
                })
            }
        </div>
    )
}

编辑2

有人要求显示此示例的减速器和商店创建外观。 它可能如下所示:

店铺创建

import { createStore } from 'redux';
import reducer from './reducer';

const initialState = {};

const store = createStore(reducer, initialState );
console.log(store.getState());
store.dispatch({type: 'SET_FILTER_VALUE', value: 2};
console.log(store.getState());

减速器

const Reducer = (state = {}, action) => {
    switch(action.type) {
        case 'SET_FILTER_VALUE': {
             return { 
                 ...state,
                 value: action.value
             }
        }
        default: {
            return state;
        }
    }
}

export default Reducer;

暂无
暂无

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

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