了解React-Redux和mapStateToProps()

2020/10/12 21:01 · javascript ·  · 0评论

我正在尝试了解react-redux的connect方法及其作为参数的功能。特别是mapStateToProps()

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

这意味着目标组件所消耗的状态与存储在商店中的状态可能具有截然不同的结构。

问:可以吗?

问:这是预期的吗?


问:这是反模式吗?

问:Is this ok?

答:是的

问:Is this expected?

是的,这是预期的(如果您正在使用react-redux)。

问:Is this an anti-pattern?

答:不,这不是反模式。

这称为“连接”组件或“使其智能化”。这是设计使然。

它使您能够将组件与状态脱钩的额外时间增加了代码的模块化程度。它还允许您将组件状态简化为应用程序状态的子集,实际上,这有助于您遵循Redux模式。

这样考虑:存储应该包含 应用程序整个状态。

对于大型应用程序,它可能包含数十个嵌套在多层中的属性。


您不想每次通话都花很多钱(昂贵)。

没有mapStateToProps或类似的东西,您很想用另一种方式来改善/简化性能。

是的,这是正确的。它只是一个帮助程序函数,可以更简单地访问状态属性

想象一下您posts的应用程序中钥匙state.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)

现在您可以在组件中使用它

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

您正确地掌握了第一部分:

mapStateToProps,将存储状态作为自变量/参数(由提供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);

可以有另一个React组件itemsFilters来处理显示并将过滤器状态持久化为Redux Store状态,Demo组件正在“监听”或“订阅” Redux Store状态过滤器,因此只要过滤器存储状态发生变化(借助filtersComponent),都会做出反应-redux检测到有更改,并通过将更改发送到所有组件来通知或“发布”所有侦听/预订的组件componentWillReceiveProps,在此示例中,由于响应状态已更改,因此将触发项目的重新过滤并刷新显示。

让我知道该示例是否令人困惑或不够清晰,无法提供更好的解释。

至于:这意味着目标组件消耗的状态与存储在商店中的状态可以具有截然不同的结构。

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

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

Redux Store状态是Redux reducer状态的组合,每个状态负责管理一小部分应用程序逻辑。可以react-redux::connect@mapStateToProps通过任何组件的帮助来访问那些reducers属性这使得Redux存储状态可在应用程序中广泛访问,而组件状态是其专有的。

reactredux示例基于Mohamed Mellouki的示例。但是使用美化掉毛规则进行验证请注意,我们使用PropTypes定义了props和dispatch方法,以便我们的编译器不会对我们尖叫。此示例还包括Mohamed的示例中缺少的一些代码行。要使用connect,您需要从react-redux导入它本示例还绑定了filterItems方法,这将防止组件出现范围问题此源代码已使用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);

此示例代码是组件入门的良好模板。

React-Redux connect用于更新每个动作的存储。

import { connect } from 'react-redux';

const AppContainer = connect(  
  mapStateToProps,
  mapDispatchToProps
)(App);

export default AppContainer;

在本博客中对此进行了非常简单和清晰的解释

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

这是描述以下行为的概述/样板mapStateToProps

(这是Redux容器的功能的大大简化的实现。)

class MyComponentContainer extends Component {
  mapStateToProps(state) {
    // this function is specific to this particular container
    return state.foo.bar;
  }

  render() {
    // This is how you get the current state from Redux,
    // and would be identical, no mater what mapStateToProps does
    const { state } = this.context.store.getState();

    const props = this.mapStateToProps(state);

    return <MyComponent {...this.props} {...props} />;
  }
}

接下来

function buildReduxContainer(ChildComponentClass, mapStateToProps) {
  return class Container extends Component {
    render() {
      const { state } = this.context.store.getState();

      const props = mapStateToProps(state);

      return <ChildComponentClass {...this.props} {...props} />;
    }
  }
}

这是一个简单的概念。Redux根据化简器中的操作创建了一个普遍存在的状态对象(存储)。像React组件一样,此状态不必在任何地方进行显式编码,但它可以帮助开发人员在reducer文件中查看默认状态对象,以可视化正在发生的事情。您将reducer导入组件中以访问文件。然后,mapStateToProps仅在其组件所需的存储中选择键/值对。可以像Redux一样创建React组件的全局版本

this.state = ({ 
cats = [], 
dogs = []
})

使用mapStateToProps()无法更改状态的结构。您要做的是仅选择组件所需的商店的键/值对,然后将值(从商店中的键/值列表)传递到组件中的prop(本地键)。您一次在列表中执行此一个值。在此过程中不会发生结构更改。

PS该商店处于本地状态。在Action Creators加入时,Reducer通常还会将状态传递给数据库,但是对于此特定的发布,首先要了解这个简单的概念。

PPS的优良作法是将每个接口的reducer分开到单独的文件中,并仅导入组件所需的reducer。

我想重新组织您提到的语句:

这意味着目标组件消耗的状态与存储在商店中的状态可能具有截然不同的结构

您可以说目标组件消耗的状态仅占Redux存储中存储状态的一小部分。换句话说,组件消耗的状态将是redux存储状态的子集。

就了解connect()方法而言,这非常简单!connect()方法可以向组件添加新道具,甚至覆盖现有道具。通过此connect方法,我们还可以访问Provider抛出给我们的redux存储的状态。结合使用两种方法对您有利,您可以将redux存储的状态添加到组件的props中。

以上是一些理论知识,我建议您看一下该视频以更好地理解语法。

是的,您可以这样做。您甚至可以处理状态并返回对象。

function mapStateToProps(state){  
  let completed = someFunction (state);
   return {
     completed : completed,  
   }
}
 

如果要将状态相关的逻辑从渲染功能转移到其外部,这将很有用。

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){  
  return {
    user:state.activeUser  
}

}

  export default connect(mapStateToProps, null)(Userdetails);
本文地址:http://javascript.askforanswer.com/lejiereact-reduxhemapstatetoprops.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!