Redux와의 연결을 사용하여 this.props에서 간단한 디스패치를 ​​얻는 방법은 무엇입니까?


107

연결하는 간단한 React 구성 요소가 있습니다 (간단한 배열 / 상태 매핑). 스토어 컨텍스트를 참조하지 않으려면 props에서 직접 "dispatch"하는 방법을 원합니다. 나는이 접근 방식을 사용하는 다른 사람들을 보았지만 어떤 이유로 이것에 액세스 할 수 없습니다 :)

현재 사용중인 각 npm 종속성의 버전은 다음과 같습니다.

"react": "0.14.3",
"react-redux": "^4.0.0",
"react-router": "1.0.1",
"redux": "^3.0.4",
"redux-thunk": "^1.0.2"

다음은 연결 방법이있는 구성 요소입니다.

class Users extends React.Component {
    render() {
        const { people } = this.props;
        return (
            <div>
                <div>{this.props.children}</div>
                <button onClick={() => { this.props.dispatch({type: ActionTypes.ADD_USER, id: 4}); }}>Add User</button>
            </div>
        );
    }
};

function mapStateToProps(state) {
    return { people: state.people };
}

export default connect(mapStateToProps, {
    fetchUsers
})(Users);

감속기를 볼 필요가 있다면 (흥미로운 것은 아니지만 여기 있습니다)

const initialState = {
    people: []
};

export default function(state=initialState, action) {
    if (action.type === ActionTypes.ADD_USER) {
        let newPeople = state.people.concat([{id: action.id, name: 'wat'}]);
        return {people: newPeople};
    }
    return state;
};

내 라우터가 redux로 어떻게 구성되어 있는지 확인해야하는 경우

const createStoreWithMiddleware = applyMiddleware(
      thunk
)(createStore);

const store = createStoreWithMiddleware(reducers);

var Route = (
  <Provider store={store}>
    <Router history={createBrowserHistory()}>
      {Routes}
    </Router>
  </Provider>
);

최신 정보

연결에서 내 자신의 디스패치를 ​​생략하면 (현재 위의 fetchUsers를 표시하고 있음) 디스패치를 ​​무료로 얻을 수 있습니다 (비동기 작업이있는 설정이 일반적으로 작동하는지 확실하지 않습니다). 사람들이 혼합하고 일치합니까, 아니면 전부입니까, 아니면 아무것도입니까?

[mapDispatchToProps]

답변:


280

기본적 mapDispatchToProps으로 dispatch => ({ dispatch }).
두 번째 인수를 위해 지정하지 않은 경우 그래서 connect(), 당신은거야 dispatch구성 요소에 소품으로 주입.

사용자 지정 함수를에 전달하면 함수로 mapDispatchToProps무엇이든 할 수 있습니다.
몇 가지 예 :

// inject onClick
function mapDispatchToProps(dispatch) {
  return {
    onClick: () => dispatch(increment())
  };
}

// inject onClick *and* dispatch
function mapDispatchToProps(dispatch) {
  return {
    dispatch,
    onClick: () => dispatch(increment())
  };
}

이것을 설정 bindActionCreators()할 수 있도록 Redux가 제공 하는 타이핑을 저장하려면 다음을 수행하십시오.

// injects onPlusClick, onMinusClick
function mapDispatchToProps(dispatch) {
  return {
    onPlusClick: () => dispatch(increment()),
    onMinusClick: () => dispatch(decrement())
  };
}

이것으로 :

import { bindActionCreators } from 'redux';

// injects onPlusClick, onMinusClick
function mapDispatchToProps(dispatch) {
  return bindActionCreators({
    onPlusClick: increment,
    onMinusClick: decrement
  }, dispatch);
}

또는 소품 이름이 액션 작성자 이름과 일치하면 더 짧습니다.

// injects increment and decrement
function mapDispatchToProps(dispatch) {
  return bindActionCreators({ increment, decrement }, dispatch);
}

원하는 경우 직접 추가 할 수 있습니다 dispatch.

// injects increment, decrement, and dispatch itself
function mapDispatchToProps(dispatch) {
  return {
    ...bindActionCreators({ increment, decrement }), // es7 spread syntax
    dispatch
  };
}

이 작업을 수행해야하는지 여부에 대한 공식적인 조언은 없습니다. connect()일반적으로 Redux를 인식하는 구성 요소와 Redux를 인식하지 않는 구성 요소 사이의 경계 역할을합니다. 우리가 일반적으로 그것을 주입 이해가되지 않는 느낌이 이유입니다 모두 결합 된 액션 제작자와 dispatch. 하지만이 작업이 필요하다고 생각되면 자유롭게하십시오.

마지막으로 지금 사용하고있는 패턴은를 호출하는 것보다 훨씬 더 짧은 지름길입니다 bindActionCreators. 당신이 할 모든 것이 return bindActionCreators일 때, 당신은 이렇게하는 대신 이렇게 호출을 생략 할 수 있습니다 :

// injects increment and decrement
function mapDispatchToProps(dispatch) {
  return bindActionCreators({ increment, decrement }, dispatch);
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App);

이렇게 쓸 수 있습니다

export default connect(
  mapStateToProps,
  { increment, decrement } // injects increment and decrement
)(App);

그러나 전달 dispatch과 같이 더 많은 사용자 정의를 원할 때마다 멋진 짧은 구문을 포기해야합니다 .


2
@ DanAbramov btw는 bindActionCreators(actionCreators, dispatch)선택 사항 의 두 번째 매개 변수 입니까? 내가 상기 코드에서 발견 // es7 spread syntax라인의이 dispatch전달되지 않습니다bindActionCreators
yonasstephen

내부 증분 방법은 무엇입니까?
Khurshid Ansari

es7 스프레드 구문은 다음과 같아야합니다function mapDispatchToProps(dispatch) { return { ...bindActionCreators({ increment, decrement }), dispatch }; }
Black

6

일반적으로 원하는 것에 따라 믹스 앤 매치 할 수 있습니다.

원하는 경우 소품으로 전달할 수 있습니다dispatch .

export default connect(mapStateToProps, (dispatch) => ({
    ...bindActionCreators({fetchUsers}, dispatch), dispatch
}))(Users);

어떻게 fetchUsers사용 되는지 (비동기 기능으로?) 모르겠지만 일반적으로 디스패치 bindActionCreators자동 바인딩 하는 것과 같은 것을 사용 하면 dispatch연결된 구성 요소에서 직접 사용하는 것에 대해 걱정할 필요가 없습니다 .

dispatch디렉토리 종류를 사용 하여 dumb , stateless 구성 요소를 redux와 결합합니다 . 휴대 성이 떨어질 수 있습니다.


3
당신이 제안하는 것은 작동하지 않습니다. 언 바운드 fetchUsers가 소품으로 주입됩니다. 단축키 표기법은 객체를 두 번째 인수로 전달할 때만 작동합니다. 함수를 전달할 때 bindActionCreators자신 을 호출해야합니다 dispatch => ({ ...bindActionCreators({ fetchUsers }, dispatch), dispatch })..
Dan Abramov

bindActionCreators에서 직접 배포하고 전달하는 이유는 무엇입니까? dispatch => ( bindActionCreators({ dispatch, fetchUsers }, dispatch))
user3711421

2

dispatch일부로 전달할 수 있지만 구성 요소 내 dispatchToProps에서 store또는에 dispatch직접 액세스하지 않는 것이 좋습니다 . connect의 두 번째 인수에서 바인딩 된 액션 제작자를 전달하면 더 나은 서비스를받을 수있을 것 같습니다.dispatchToProps

여기에 게시 된 예제를 참조하십시오 https://stackoverflow.com/a/34455431/2644281 이렇게 "이미 바인딩 된 작업 생성자"를 전달하는 방법에 대해 구성 요소가 상점 / 디스패치에 대해 직접 알거나 의존 할 필요가 없습니다. .

짧게 말해서 죄송합니다. 더 많은 정보로 업데이트하겠습니다.

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