React-Redux 및 mapStateToProps () 이해


220

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

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

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

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


11
믹스에 다른 답변을 추가하고 싶지 않습니다 ...하지만 아무도 실제로 귀하의 질문에 대답하지 않는다는 것을 알고 있습니다 ... 내 의견으로 는 반 패턴이 아닙니다 . 키는 mapStateTo Props 이름 에 있으며 구성 요소가 사용할 읽기 전용 속성을 전달합니다. 컨테이너 구성 요소를 자주 사용하여 상태를 가져 와서 프레젠테이션 구성 요소로 전달하기 전에 변경합니다.
매튜 브렌트

3
내 표현 적 요소가 훨씬 간단이 방법은 ... 나는 렌더링 수 있습니다 this.props.someData반대로 this.props.someKey[someOtherKey].someData... 메이크업 감각?
매튜 브렌트

3
이 튜토리얼은 충분히 설명합니다 : learn.co/lessons/map-state-to-props-readme
Ayan

안녕 파블로, 선택한 답변을 다시 고려하십시오.
vsync

어떻게 다시 생각하십니까?
Pablo Barría Urenda

답변:


56

Q : Is this ok?
A : 예

Q : Is this expected?
그렇습니다 (react-redux를 사용하는 경우).

Q : Is this an anti-pattern?
A : 아니요. 이것은 안티 패턴이 아닙니다.

구성 요소를 "연결"또는 "스마트하게 만들기"라고합니다. 의도적으로 설계된 것입니다.

코드의 모듈성을 증가시키는 추가 시간 동안 구성 요소를 상태에서 분리 할 수 ​​있습니다. 또한 구성 요소 상태를 응용 프로그램 상태의 하위 집합으로 단순화하여 실제로 Redux 패턴을 준수하는 데 도움이됩니다.

이 방법에 대해 생각해보십시오. 상점은 애플리케이션 의 전체 상태 를 포함 해야합니다.
대규모 응용 프로그램의 경우 여기에는 여러 계층 깊이에 중첩 된 수십 가지 속성이 포함될 수 있습니다.
각 통화마다 모든 것을 운반하고 싶지 않습니다 (비싼).

mapStateToProps그것의 유사체가 없거나 그와 유사한 것이 없다면 , 당신은 성과 / 단순화를 개선하기위한 다른 방법으로 당신의 상태를 개척하려는 유혹을받을 것입니다.


6
전체 저장소에 대한 모든 구성 요소에 대한 액세스 권한을 제공하더라도 성능과 관련이 있다고 생각하지는 않습니다. 객체를 전달하면 항상 동일한 객체 이므로 메모리를 차지하지 않습니다 . 필요한 부분을 구성 요소로 가져 오는 유일한 이유는 아마도 두 가지 이유 일 것입니다. (1) -더 쉬운 액세스 용이 (2) -구성 요소가 속하지 않은 상태에서 구성 요소가 엉망이되는 버그를 피하십시오
vsync

@vsync 어떻게 더 쉽게 액세스 할 수 있는지 설명해 주시겠습니까? 이제 전역 소품을 참조 할 필요없이 로컬 소품을 사용할 수있어 더 읽기 쉽습니다.
Siddhartha

또한 상태가 불변으로 전달 될 때 구성 요소가 상태에 속하지 않는 방법은 무엇입니까?
Siddhartha

상태가 불변이라면 괜찮습니다.하지만 여전히 좋은 습관으로, 관련 부품 만 구성 요소에 노출하는 것이 좋습니다. 또한 다른 개발자가 상태 객체 의 어느 부분 이 해당 구성 요소와 관련이 있는지 더 잘 이해하도록 도와줍니다 . "쉬운 접근"과 관련하여, 일부 깊은 상태에 대한 경로는 소품으로 구성 요소에 직접 전달되고 해당 구성 요소는 장면 뒤의 Redux 사실에 대해 눈에 띄지 않습니다. 구성 요소는 사용되는 상태 관리 시스템을 신경 쓰지 않아야하며받는 소품과 만 작동해야합니다.
vsync

119

예, 맞습니다. 상태 속성에 더 간단하게 액세스 할 수있는 도우미 함수일뿐입니다.

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

나는 뭔가를 놓칠 수 있다고 생각하지만 과 및 행동 dispatch => bindActionCreators({fetchPosts, deletePost}, dispatch)은 어디서 전달됩니까? fetchPostsdeletePost
ilyo

@ilyo 이들은 액션 크리에이터입니다. 가져와야합니다
webdeb

2
좋은 대답입니다! 나는이 코드 덩어리 state => state.posts( mapStateToProps함수)가 React에게 어떤 상태가 업데이트 될 때 구성 요소를 다시 렌더링 할 것인지 알려줄 것이라고 강조하는 것이 좋습니다 .
Miguel Péres

38

첫 번째 부분이 맞았습니다.

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 스토어 상태 액세스 가능한 앱을 넓게 만듭니다.


5

반응 & 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);

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


2

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

import { connect } from 'react-redux';

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

export default AppContainer;

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

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


좋은 매뉴얼 formapStateToProps thegreatcodeadventure.com/…
zloctb

1

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

-2
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);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.