Понимание React-Redux и mapStateToProps()
Я пытаюсь понять метод подключения react-redux и функции, которые он принимает в качестве параметров. В частности mapStateToProps().
Как я понимаю, возвращаемое значение mapStateToProps будет объект, производный от состояния (как он живет в хранилище), ключи которого будут переданы в целевой компонент (компонент connect применяется к) в качестве реквизитов.
это означает, что состояние, потребляемое вашим целевым компонентом, может иметь совершенно другую структуру состояние, как оно хранится в вашем магазине.
Q: это нормально?
Вопрос: это нормально?
Вопрос: это анти-паттерн?
6 ответов:
Q:
Is this ok?
A: даQ:
Is this expected?
Да, это ожидается (если вы используете react-redux).Q:
Is this an anti-pattern?
A: нет, это не анти-паттерн.это называется "подключение" вашего компонента или"сделать его умным". Это сделано специально.
Это позволяет отделить ваш компонент от вашего состояния дополнительное время, которое увеличивает модульность вашего кода. Это также позволяет упростить состояние компонента в виде подмножество вашего состояния приложения, которое, по сути, помогает вам соответствовать шаблону Redux.
подумайте об этом так: магазин должен содержать весь состоянии вашего заявления.
Для больших приложений это может содержать десятки свойств, вложенных в несколько слоев глубоко.
Вы не хотите, чтобы тащить все это вокруг на каждый вызов (дорого).без
mapStateToPropsили какой-то аналог этого, вы бы соблазнились вырезать свое состояние еще один способ повысить производительность / упростить.
Да, это правильно. Его просто вспомогательная функция, чтобы иметь более простой способ доступа к свойствам состояния
представьте, что у вас есть
postsключ в вашем приложенииstate.postsstate.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:
deletePostconst 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имеет состояние хранилища в качестве аргумента / 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);может быть еще один компонент react под названием
itemsFiltersкоторые обрабатывают отображение и сохраняют состояние фильтра в состоянии Redux Store, демонстрационный компонент "прослушивает" или "подписывается" на фильтры состояния Redux Store, поэтому всякий раз, когда фильтры сохраняют изменения состояния (с помощьюfiltersComponent) react-redux обнаруживает, что произошло изменение и уведомляет или "публикует" все прослушивающие / подписанные компоненты, отправляя изменения в ихcomponentWillReceivePropsкоторый в этом примере вызовет повторный фильтр элементов и обновит дисплей из-за того, что состояние react изменилось.Дайте мне знать, если пример сбивает с толку или не достаточно ясно, чтобы обеспечить лучшее объяснение.
для: это означает, что состояние, потребляемое вашим целевым компонентом, может иметь совершенно иную структуру, чем состояние, хранящееся в вашем магазине.
Я не понял вопрос, но просто знайте, что состояние реакции (
this.setState) полностью отличается от состояния магазина Redux!состояние react используется для обработки перерисовки и поведения компонента react. Состояние react содержится исключительно в компоненте the.
состояние магазина Redux-это комбинация состояний редукторов Redux, каждый из которых отвечает за управление небольшой частью логики приложения. Эти атрибуты редукторов могут быть доступны с помощью
react-redux::connect@mapStateToPropsлюбой компонент! Которые делают состояние магазина Redux доступным для широкого приложения, в то время как состояние компонента является эксклюзивным для себя.
этой реагировать & возвращение пример основан на примере Мохамеда Меллуки. Но проверяет с помощью принаряжать и правила пылеобразования. Обратите внимание, что мы определяем наши реквизиты и отправка методы с использованием PropTypes чтобы наш компилятор не кричал на нас. Этот пример также включал некоторые строки кода, которые отсутствовали в Мохаммеде образец. Для использования подключения вам нужно будет импортировать его из react-redux. Этот например,персонализация метод filterItems это предотвратит scope проблемы в элемент компонент. Этот исходный код был автоматически отформатирован с помощью JavaScript принаряжать.
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 connect.
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);
Comments