[javascript] React-Redux 및 mapStateToProps () 이해

react-redux의 연결 방법과 매개 변수로 사용되는 기능을 이해하려고합니다. 특히 mapStateToProps().

내가 이해하는 방식의 반환 값은 mapStateToProps상태 (상점에있는 상태)에서 파생 된 객체이며 키는 대상 구성 요소 (구성 요소 연결이 적용됨)에 소품으로 전달됩니다.

이는 대상 구성 요소가 소비 한 상태가 상점에 저장된 상태와 크게 다른 구조를 가질 수 있음을 의미합니다.

Q : 괜찮습니까?
Q : 이것이 예상됩니까?
Q : 반 패턴입니까?



답변

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는 상점 상태를 인수 / 매개 변수 (로 제공 react-redux::connect)로 가지며 구성 요소를 상점 상태의 특정 부분과 링크하는 데 사용됩니다.

연결한다는 것은 mapStateToProps건설 시간에 소품으로 반환되는 물건이 소품으로 제공되며 이후의 모든 변경 사항은를 통해 제공됨을 의미 componentWillReceiveProps합니다.

Observer 디자인 패턴을 알고 있다면 정확히 그 또는 작은 변형입니다.

예를 들어 더 명확하게하는 데 도움이됩니다.

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);

itemsFilters디스플레이를 처리하고 필터 상태를 Redux Store 상태로 유지하는 다른 반응 구성 요소가있을 수 있습니다 . Demo 구성 요소는 Redux Store 상태 필터를 “청취”또는 “구독”하여 필터 저장 상태가 변경 될 때마다 ( filtersComponent반응 을 통해 ) 반응합니다 -redux는 변경 사항이 있음을 감지 componentWillReceiveProps하고이 예에서 항목의 재 필터링을 트리거하고 반응 상태가 변경되어 디스플레이를 새로 고치는 변경 사항을 변경 사항으로 전송하여 청취 / 구독 된 모든 구성 요소에 알리거나 “게시”합니다. .

더 나은 설명을 제공하기에 예제가 혼란 스럽거나 명확하지 않은 경우 알려주십시오.

대상 : 대상 구성 요소가 소비 한 상태가 상점에 저장된 상태와 크게 다른 구조를 가질 수 있음을 의미합니다.

나는 질문을 얻지 못했지만 반응 상태 ( this.setState)가 Redux Store 상태와 완전히 다릅니다.

반응 상태는 반응 구성 요소의 다시 그리기 및 동작을 처리하는 데 사용됩니다. 반응 상태는 구성 요소에 독점적으로 포함됩니다.

Redux Store 상태는 Redux 감속기 상태의 조합이며 각각 작은 부분의 앱 논리를 관리합니다. 이러한 감속기 속성은 react-redux::connect@mapStateToProps모든 구성 요소 의 도움으로 액세스 할 수 있습니다 ! 구성 요소 상태가 독점적 인 반면 Redux 스토어 상태 액세스 가능한 앱을 넓게 만듭니다.


답변

반응 & redux 예제는 Mohamed Mellouki의 예제를 기반으로합니다. 그러나 prettifylinting 규칙을 사용하여 유효성을 검사 합니다. 컴파일러가 소리를 내지 않도록 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);

이 예제 코드는 구성 요소의 시작 위치에 적합한 템플릿입니다.


답변

React-Redux connect 는 모든 작업에 대한 저장소를 업데이트하는 데 사용됩니다.

import { connect } from 'react-redux';

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

export default AppContainer;

블로그 에서 매우 간단하고 명확하게 설명되어 있습니다.

Redux 연결을 이해하기 위해 github 프로젝트를 복제하거나 해당 블로그의 코드를 복사하여 붙여 넣을 수 있습니다.


답변

다음은 동작을 설명하기위한 개요 / 보일러 판입니다 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} />;
    }
  }
}


답변

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);