Понимание React-Redux и mapStateToProps()



Я пытаюсь понять метод подключения react-redux и функции, которые он принимает в качестве параметров. В частности mapStateToProps().



Как я понимаю, возвращаемое значение mapStateToProps будет объект, производный от состояния (как он живет в хранилище), ключи которого будут переданы в целевой компонент (компонент connect применяется к) в качестве реквизитов.



это означает, что состояние, потребляемое вашим целевым компонентом, может иметь совершенно другую структуру состояние, как оно хранится в вашем магазине.



Q: это нормально?

Вопрос: это нормально?

Вопрос: это анти-паттерн?

927   6  

6 ответов:

Q:Is this ok?
A: да

Q:Is this expected?
Да, это ожидается (если вы используете react-redux).

Q:Is this an anti-pattern?
A: нет, это не анти-паттерн.

это называется "подключение" вашего компонента или"сделать его умным". Это сделано специально.

Это позволяет отделить ваш компонент от вашего состояния дополнительное время, которое увеличивает модульность вашего кода. Это также позволяет упростить состояние компонента в виде подмножество вашего состояния приложения, которое, по сути, помогает вам соответствовать шаблону 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 имеет состояние хранилища в качестве аргумента / 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-Reduxconnect используется для обновления хранилища для каждого действия.

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

    Ничего не найдено.