Làm cách nào để nhận công văn đơn giản từ this.props bằng cách sử dụng connect w / Redux?


107

Tôi có một thành phần React đơn giản mà tôi kết nối (ánh xạ một mảng / trạng thái đơn giản qua). Để tránh tham chiếu đến bối cảnh cho cửa hàng, tôi muốn có một cách để lấy "công văn" trực tiếp từ các đạo cụ. Tôi đã thấy những người khác sử dụng phương pháp này nhưng không có quyền truy cập vào cách này vì một số lý do :)

Đây là các phiên bản của từng phụ thuộc npm mà tôi đang sử dụng hiện tại

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

Đây là phương thức thành phần w / connect

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

Nếu bạn cần xem bộ giảm tốc (không có gì thú vị nhưng nó ở đây)

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

Nếu bạn cần xem bộ định tuyến của tôi được định cấu hình như thế nào w / redux

const createStoreWithMiddleware = applyMiddleware(
      thunk
)(createStore);

const store = createStoreWithMiddleware(reducers);

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

cập nhật

có vẻ như nếu tôi bỏ qua công văn của riêng mình trong kết nối (hiện ở trên tôi đang hiển thị Người dùng tìm nạp), tôi sẽ nhận được công văn miễn phí (chỉ không chắc liệu đây có phải là cách thiết lập các hành động w / async thường hoạt động hay không). Người ta trộn và kết hợp hay là tất cả hoặc không có gì?

[mapDispatchToProps]

Câu trả lời:


280

Theo mặc định mapDispatchToPropslà chỉ dispatch => ({ dispatch }).
Vì vậy, nếu bạn không chỉ định đối số thứ hai connect(), bạn sẽ được dispatchđưa vào làm chỗ dựa trong thành phần của mình.

Nếu bạn chuyển một hàm tùy chỉnh cho mapDispatchToProps, bạn có thể làm bất cứ điều gì với hàm.
Một vài ví dụ:

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

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

Để tiết kiệm cho bạn một số thao tác gõ Redux cung cấp bindActionCreators()cho phép bạn thực hiện điều này:

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

vào cái này:

import { bindActionCreators } from 'redux';

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

hoặc thậm chí ngắn hơn khi tên prop khớp với tên người tạo hành động:

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

Nếu bạn muốn, bạn chắc chắn có thể thêm vào dispatchđó bằng tay:

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

Không có lời khuyên chính thức nào về việc bạn có nên làm điều này hay không. connect()thường đóng vai trò là ranh giới giữa các thành phần nhận biết Redux và không nhận biết Redux. Đây là lý do tại sao chúng tôi thường cảm thấy rằng không hợp lý khi đưa cả những người sáng tạo hành động bị ràng buộc và dispatch. Nhưng nếu bạn cảm thấy cần phải làm điều này, hãy cứ tự nhiên.

Cuối cùng, kiểu bạn đang sử dụng ngay bây giờ là một phím tắt thậm chí còn ngắn hơn cách gọi bindActionCreators. Khi tất cả những gì bạn làm là quay trở lại bindActionCreators, bạn có thể bỏ qua cuộc gọi như vậy thay vì thực hiện điều này:

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

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

có thể được viết như thế này

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

Tuy nhiên, bạn sẽ phải từ bỏ cú pháp ngắn gọn đẹp mắt đó bất cứ khi nào bạn muốn một cái gì đó tùy chỉnh hơn, chẳng hạn như truyền dispatch.


2
@DanAbramov btw là tham số thứ hai trong bindActionCreators(actionCreators, dispatch)tùy chọn? Tôi nhận thấy trong mã của bạn ở // es7 spread syntaxdòng, dòng dispatchkhông được chuyển đếnbindActionCreators
yonasstephen.

bên trong phương thức gia tăng là gì?
Khurshid Ansari

Cú pháp lây lan của es7 nên là function mapDispatchToProps(dispatch) { return { ...bindActionCreators({ increment, decrement }), dispatch }; }
Đen

6

Bạn thường có thể trộn và kết hợp dựa trên những gì bạn muốn.

Bạn có thể vượt qua dispatchtrên như một chỗ dựa nếu đó là những gì bạn muốn:

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

Tôi không chắc fetchUsersđược sử dụng như thế nào (như một hàm không đồng bộ?), Nhưng bạn thường sử dụng một cái gì đó như bindActionCreatorsđể tự động liên kết gửi và sau đó bạn sẽ không phải lo lắng về việc sử dụng dispatchtrực tiếp trong các thành phần được kết nối.

Sử dụng dispatchloại thư mục kết hợp thành phần câm , không trạng thái với redux. Điều này có thể làm cho nó ít di động hơn.


3
Những gì bạn đang đề xuất sẽ không hoạt động. Bạn sẽ nhận được một mũi fetchUserstiêm không ràng buộc như một chỗ dựa. Ký hiệu lối tắt chỉ hoạt động khi bạn truyền một đối tượng làm đối số thứ hai. Khi bạn vượt qua một chức năng bạn phải gọi bindActionCreatorscho mình: dispatch => ({ ...bindActionCreators({ fetchUsers }, dispatch), dispatch }).
Dan Abramov

Tại sao lại lây lan và chuyển trực tiếp trong công văn trong bindActionCreators? dispatch => ( bindActionCreators({ dispatch, fetchUsers }, dispatch))
user3711421 Ngày

2

Mặc dù bạn có thể chuyển giao dispatchnhư một phần của nó dispatchToProps, nhưng tôi khuyên bạn nên tránh truy cập storehoặc dispatchtrực tiếp từ bên trong các thành phần của bạn. Có vẻ như bạn sẽ được phục vụ tốt hơn bằng cách chuyển một trình tạo hành động bị ràng buộc trong đối số thứ 2 của connectdispatchToProps

Xem ví dụ tôi đã đăng ở đây https://stackoverflow.com/a/34455431/2644281 về cách chuyển xuống "người tạo hành động đã bị ràng buộc" theo cách này, các thành phần của bạn không cần trực tiếp biết hoặc phụ thuộc vào cửa hàng / công văn .

Xin lỗi để được ngắn gọn. Tôi sẽ cập nhật thêm thông tin.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.