理解React-Redux和mapStateToProps()

Pab*_*nda 196 javascript redux react-redux

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

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

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

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

web*_*deb 112

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

想象一下posts,你的应用程序中有一把钥匙state.posts

state.posts //
/*    
{
  currentPostId: "",
  isFetching: false,
  allPosts: {}
}
*/
Run Code Online (Sandbox Code Playgroud)

和组件 Posts

默认情况下,connect()(Posts)将为连接的组件提供所有状态道具

const Posts = ({posts}) => (
  <div>
    {/* access posts.isFetching, access posts.allPosts */}
  </div> 
)
Run Code Online (Sandbox Code Playgroud)

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

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

connect(
  state => state.posts
)(Posts)
Run Code Online (Sandbox Code Playgroud)

mapDispatchToProps

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

bindActionCreators你能做到这一点也更容易喜欢

connect(
  state => state.posts,
  dispatch => bindActionCreators({fetchPosts, deletePost}, dispatch)
)(Posts)
Run Code Online (Sandbox Code Playgroud)

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

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

关于actionCreators的更新..

actionCreator的一个示例: deletePost

const deletePostAction = (id) => ({
  action: 'DELETE_POST',
  payload: { id },
})
Run Code Online (Sandbox Code Playgroud)

所以,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;
  }, {})
}
Run Code Online (Sandbox Code Playgroud)

  • 不错的答案!我认为强调这块代码 `state =&gt; state.posts`(`mapStateToProps` 函数)将告诉 React 哪些状态会在更新时触发组件的重新渲染也很好。 (2认同)

小智 49

问:Is this ok?
答:是的

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

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

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

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

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

如果没有mapStateToProps或类似的模拟,你会倾向于以另一种方式来改变你的状态以提高性能/简化.

  • 我不认为让每个组件访问整个商店,无论它有多大,都与性能有关.传递对象不会占用内存,因为它始终是**相同的**对象.将组件所需的部件带到组件的唯一原因可能有两个:`(1)-`更容易深入访问`(2)-`避免组件可能搞乱的错误状态不属于它的状态 (5认同)

小智 35

你得到了第一部分:

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);
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

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


Pat*_*hon 5

这种反应Redux的例子是基于关闭穆罕默德Mellouki的例子.但验证使用美化linting规则.请注意,我们使用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);
Run Code Online (Sandbox Code Playgroud)

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