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

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

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

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


当前回答

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

假设你在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);

This react & redux example is based off Mohamed Mellouki's example. But validates using prettify and linting rules. Note that we define our props and dispatch methods using PropTypes so that our compiler doesn't scream at us. This example also included some lines of code that had been missing in Mohamed's example. To use connect you will need to import it from react-redux. This example also binds the method filterItems this will prevent scope problems in the component. This source code has been auto formatted using 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连接用于更新每个操作的存储。

import { connect } from 'react-redux';

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

export default AppContainer;

这篇博客里解释得非常简单明了。

你可以克隆github项目或复制粘贴从博客的代码来理解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;
  }, {})
}

是的,你可以做到。您甚至还可以处理状态并返回对象。

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

如果您想将与状态相关的逻辑从呈现函数转移到它的外部,这将非常有用。