首页 文章

理解React-Redux和mapStateToProps()

提问于
浏览
155

我试图理解react-redux的连接方法,以及它作为参数所用的函数 . 特别是 mapStateToProps() .

我理解它的方式, mapStateToProps 的返回值将是一个从状态派生的对象(因为它存在于商店中),其键将作为道具传递给目标组件(应用组件连接) .

这意味着目标组件所使用的状态可能与存储在商店中的状态具有完全不同的结构 .

问:这样可以吗?
问:这是预期的吗?
问:这是一种反模式吗?

6 回答

  • 28

    问: Is this ok?
    答:是的

    问: Is this expected?
    是的,这是预期的(如果您使用react-redux) .

    问: Is this an anti-pattern?
    答:不,这不是反模式 .

    它被称为“连接”您的组件或“使其变得聪明” . 这是设计的 .

    它允许您将组件与状态分离一段额外的时间,从而增加代码的模块性 . 它还允许您将组件状态简化为应用程序状态的子集,这实际上可以帮助您遵守Redux模式 .

    以这种方式思考:商店应该包含应用程序的整个状态 .
    对于大型应用程序,这可能包含嵌套多层深层的许多属性 .
    你不想在每次通话时都把这一切都拿走(费用昂贵) .

    如果没有 mapStateToProps 或其中的某些类似物,您很可能会以另一种方式来改变您的状态以提高性能/简化 .

  • 5

    是的,这是正确的 . 它只是一个辅助函数,可以更简单地访问您的状态属性

    想象一下,你的App中有一个 postsstate.posts

    state.posts //
    /*    
    {
      currentPostId: "",
      isFetching: false,
      allPosts: {}
    }
    */
    

    和组件 Posts

    默认情况下, connect()(Posts) 将使所有状态道具可用于连接的组件

    const Posts = ({posts}) => (
      <div>
        {/* access posts.isFetching, access posts.allPosts */}
      </div> 
    )
    

    现在,当您将 state.posts 映射到组件时,它会变得更好一些

    const Posts = ({isFetching, allPosts}) => (
      <div>
        {/* access isFetching, allPosts directly */}
      </div> 
    )
    
    connect(
      state => state.posts
    )(Posts)
    

    mapDispatchToProps

    通常你必须写 dispatch(anActionCreator())

    bindActionCreators 你也可以更容易地做到这一点

    connect(
      state => state.posts,
      dispatch => bindActionCreators({fetchPosts, deletePost}, dispatch)
    )(Posts)
    

    现在,您可以在Component中使用它

    const Posts = ({isFetching, allPosts, fetchPosts, deletePost }) => (
      <div>
        <button onClick={() => fetchPosts()} />Fetch posts</button>
        {/* access isFetching, allPosts directly */}
      </div> 
    )
    

    关于actionCreators的更新..

    actionCreator的一个示例: deletePost

    const deletePostAction = (id) => ({
      action: 'DELETE_POST',
      payload: { id },
    })
    

    所以, bindActionCreators 只会采取你的行动,将它们包装成 dispatch 电话 . (我没有阅读redux的源代码,但实现可能如下所示:

    const bindActionCreators = (actions, dispatch) => {
      return Object.keys(actions).reduce(actionsMap, actionNameInProps => {
        actionsMap[actionNameInProps] = (...args) => dispatch(actions[actionNameInProps].call(null, ...args))
        return actionsMap;
      }, {})
    }
    
  • 2

    你的第一部分是正确的:

    mapStateToProps 将Store状态作为参数/ param(由 react-redux::connect 提供),并用于将组件与存储状态的某些部分链接 .

    通过链接我的意思是 mapStateToProps 返回的对象将在施工时作为道具提供,任何后续更改将通过 componentWillReceiveProps 提供 .

    如果你知道观察者的设计模式,它就是它或它的小变化 .

    一个例子将有助于使事情更清楚:

    import React, {
        Component,
    } from 'react-native';
    
    class ItemsContainer extends Component {
        constructor(props) {
            super(props);
    
            this.state = {
                items: props.items, //provided by connect@mapStateToProps
                filteredItems: this.filterItems(props.items, props.filters),
            };
        }
    
        componentWillReceiveProps(nextProps) {
            this.setState({
                filteredItems: this.filterItems(this.state.items, nextProps.filters),
            });
        }
    
        filterItems = (items, filters) => { /* return filtered list */ }
    
        render() {
            return (
                <View>
                    // display the filtered items
                </View>
            );
        }
    }
    
    module.exports = connect(
        //mapStateToProps,
        (state) => {
            items: state.App.Items.List,
            filters: state.App.Items.Filters,
            //the State.App & state.App.Items.List/Filters are reducers used as an example.
        }
        // mapDispatchToProps,  that's another subject
    )(ItemsContainer);
    

    可以有另一个名为 itemsFilters 的反应组件处理显示并将过滤器状态保持到Redux Store状态,Demo组件是"listening"或"subscribed"到Redux Store状态过滤器,因此每当过滤器存储状态更改时(借助 filtersComponent )react-redux通过将更改发送到 componentWillReceiveProps 来检测是否存在更改并通知或"publish"所有侦听/订阅组件在此示例中将触发项目的重新过滤器并由于反应状态已更改而刷新显示 .

    如果这个例子令人困惑或不够清楚,无法提供更好的解释,请告诉我 .

    至于:这意味着目标组件所使用的状态与存储在商店中的状态可能具有完全不同的结构 .

    我没有得到问题,但只知道反应状态( this.setState )与Redux Store状态完全不同!

    反应状态用于处理反应组分的重绘和行为 . 反应状态仅包含在组件中 .

    Redux Store状态是Redux reducer状态的组合,每个状态负责管理一小部分app逻辑 . 任何组件都可以在 react-redux::connect@mapStateToProps 的帮助下访问这些reducers属性!这使得Redux存储状态可以访问应用程序范围,而组件状态是独有的 .

  • 101

    这个例子基于穆罕默德·梅卢基(Mohamed Mellouki)的例子 . 但是使用prettifylinting rules进行验证 . 请注意,我们使用PropTypes定义了props和dispatch方法,以便我们的编译器不会使用't scream at us. This example also included some lines of code that had been missing in Mohamed'示例 . 要使用连接,您需要从react-redux导入它 . 这个例子也是binds方法filterItems这将阻止component中的scope问题 . 此源代码已使用JavaScript Prettify自动格式化 .

    import React, { Component } from 'react-native';
    import { connect } from 'react-redux';
    import PropTypes from 'prop-types';
    
    class ItemsContainer extends Component {
      constructor(props) {
        super(props);
        const { items, filters } = props;
        this.state = {
          items,
          filteredItems: filterItems(items, filters),
        };
        this.filterItems = this.filterItems.bind(this);
      }
    
      componentWillReceiveProps(nextProps) {
        const { itmes } = this.state;
        const { filters } = nextProps;
        this.setState({ filteredItems: filterItems(items, filters) });
      }
    
      filterItems = (items, filters) => {
        /* return filtered list */
      };
    
      render() {
        return <View>/*display the filtered items */</View>;
      }
    }
    
    /*
    define dispatch methods in propTypes so that they are validated.
    */
    ItemsContainer.propTypes = {
      items: PropTypes.array.isRequired,
      filters: PropTypes.array.isRequired,
      onMyAction: PropTypes.func.isRequired,
    };
    
    /*
    map state to props
    */
    const mapStateToProps = state => ({
      items: state.App.Items.List,
      filters: state.App.Items.Filters,
    });
    
    /*
    connect dispatch to props so that you can call the methods from the active props scope.
    The defined method `onMyAction` can be called in the scope of the componets props.
    */
    const mapDispatchToProps = dispatch => ({
      onMyAction: value => {
        dispatch(() => console.log(`${value}`));
      },
    });
    
    /* clean way of setting up the connect. */
    export default connect(mapStateToProps, mapDispatchToProps)(ItemsContainer);
    

    此示例代码是组件起始位置的良好模板 .

  • 19

    React-Redux connect 用于为每个操作更新存储 .

    import { connect } from 'react-redux';
    
    const AppContainer = connect(  
      mapStateToProps,
      mapDispatchToProps
    )(App);
    
    export default AppContainer;
    

    这个非常简单明了地解释了这个问题 .

    您可以克隆github项目或复制粘贴代码从该博客了解Redux连接 .

  • -1
    import React from 'react';
    import {connect} from 'react-redux';
    import Userlist from './Userlist';
    
    class Userdetails extends React.Component{
    
    render(){
        return(
            <div>
                <p>Name : <span>{this.props.user.name}</span></p>
                <p>ID : <span>{this.props.user.id}</span></p>
                <p>Working : <span>{this.props.user.Working}</span></p>
                <p>Age : <span>{this.props.user.age}</span></p>
            </div>
        );
     }
    

    }

    function mapStateToProps(state){  *state is your redux-store object* 
      return {
        user:state.activeUser  
    }
    

    }

    export default connect(mapStateToProps)(Userdetails);
    

相关问题