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

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

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

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


当前回答

下面是描述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} />;
    }
  }
}

其他回答

你第一部分答对了:

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

通过链接,我的意思是mapStateToProps返回的对象将在构造时作为props提供,任何后续的更改将通过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);

There can be another react component called itemsFilters that handle the display and persisting the filter state into Redux Store state, the Demo component is "listening" or "subscribed" to Redux Store state filters so whenever filters store state changes (with the help of filtersComponent) react-redux detect that there was a change and notify or "publish" all the listening/subscribed components by sending the changes to their componentWillReceiveProps which in this example will trigger a refilter of the items and refresh the display due to the fact that react state has changed.

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

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

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

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

Redux Store状态是Redux reducers状态的组合,每个状态负责管理一小部分应用程序逻辑。任何组件都可以在react-redux::connect@mapStateToProps的帮助下访问这些reducers属性!这使得Redux商店状态可访问的应用程序范围内,而组件状态是专属于自己。

是的,这是正确的。它只是一个帮助函数,有一个更简单的方法来访问你的状态属性

假设你在App state.posts中有一个posts键

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

和组件职位

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

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

现在当你绘制州地图。post到你的组件会更好一些

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

bindactioncreator会接受你的动作,把它们包装到分派调用中。(我没有阅读redux的源代码,但实现可能是这样的:

const bindActionCreators = (actions, dispatch) => {
  return Object.keys(actions).reduce(actionsMap, actionNameInProps => {
    actionsMap[actionNameInProps] = (...args) => dispatch(actions[actionNameInProps].call(null, ...args))
    return actionsMap;
  }, {})
}
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);

问:这样可以吗? 是的

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

问:这是反模式吗? 答:不,这不是反模式。

这被称为“连接”组件或“使其智能”。这是设计出来的。

它允许您在额外的时间内将组件与状态解耦,从而增加代码的模块化。它还允许您将组件状态简化为应用程序状态的子集,这实际上有助于您遵守Redux模式。

可以这样考虑:存储应该包含应用程序的整个状态。 对于大型应用程序,这可能包含数十个嵌套在多层深处的属性。 你不希望每次通话都带着这些东西(很贵)。

如果没有mapStateToProps或类似的东西,您可能会倾向于以另一种方式分割状态以提高性能/简化。

下面是描述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} />;
    }
  }
}