Bagaimana cara mendapatkan pengiriman sederhana dari this.props menggunakan connect w / Redux?

107

Saya memiliki komponen React sederhana yang saya hubungkan (memetakan array / status sederhana). Untuk menghindari referensi konteks untuk toko, saya ingin cara untuk mendapatkan "pengiriman" langsung dari alat peraga. Saya telah melihat orang lain menggunakan pendekatan ini tetapi tidak memiliki akses ke ini karena beberapa alasan :)

Ini adalah versi dari setiap ketergantungan npm yang saya gunakan saat ini

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

Berikut adalah metode komponen w / hubungkan

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

Jika Anda perlu melihat peredam (tidak ada yang menarik selain ini dia)

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

Jika Anda perlu melihat bagaimana router saya dikonfigurasi w / redux

const createStoreWithMiddleware = applyMiddleware(
      thunk
)(createStore);

const store = createStoreWithMiddleware(reducers);

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

memperbarui

Sepertinya jika saya menghilangkan pengiriman saya sendiri di koneksi (saat ini di atas saya menunjukkan fetchUsers), saya akan mendapatkan pengiriman gratis (hanya tidak yakin apakah ini adalah cara penyiapan w / tindakan asinkron biasanya berfungsi). Apakah orang mencampur dan mencocokkan atau semuanya atau tidak sama sekali?

[mapDispatchToProps]

Toran Billups
sumber

Jawaban:

280

Secara default mapDispatchToPropshanya dispatch => ({ dispatch }).
Jadi jika Anda tidak menentukan argumen kedua connect(), Anda akan dispatchdimasukkan sebagai prop di komponen Anda.

Jika Anda meneruskan fungsi kustom ke mapDispatchToProps, Anda dapat melakukan apa saja dengan fungsi tersebut.
Beberapa contoh:

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

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

Untuk menghemat beberapa pengetikan yang disediakan Redux bindActionCreators()yang memungkinkan Anda mengubah ini:

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

ke dalam ini:

import { bindActionCreators } from 'redux';

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

atau bahkan lebih pendek ketika nama prop cocok dengan nama pembuat aksi:

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

Jika mau, Anda pasti bisa menambahkannya dispatchdengan tangan:

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

Tidak ada nasihat resmi apakah Anda harus melakukan ini atau tidak. connect()biasanya berfungsi sebagai batas antara komponen Redux-aware dan Redux-unaware. Ini sebabnya kami biasanya merasa bahwa itu tidak masuk akal untuk menyuntikkan baik pencipta tindakan terikat dan dispatch. Tetapi jika Anda merasa perlu melakukan ini, silakan.

Terakhir, pola yang Anda gunakan saat ini adalah pintasan yang bahkan lebih pendek daripada menelepon bindActionCreators. Ketika semua yang Anda lakukan adalah kembali bindActionCreators, Anda dapat menghilangkan panggilan tersebut daripada melakukan ini:

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

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

bisa ditulis seperti ini

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

Namun Anda harus melepaskan sintaks pendek yang bagus itu setiap kali Anda menginginkan sesuatu yang lebih khusus, seperti meneruskan dispatchjuga.

Dan Abramov
sumber
2
@DanAbramov btw adalah parameter kedua bindActionCreators(actionCreators, dispatch)opsional? Saya perhatikan di kode Anda di // es7 spread syntaxtelepon, dispatchtidak diteruskan kebindActionCreators
yonasstephen
apa yang di dalam metode increment?
Khurshid Ansari
es7 menyebar sintaks harus function mapDispatchToProps(dispatch) { return { ...bindActionCreators({ increment, decrement }), dispatch }; }
Hitam
6

Anda biasanya dapat mencampur dan mencocokkan berdasarkan apa yang Anda suka.

Anda dapat meneruskan dispatchsebagai properti jika itu yang Anda inginkan:

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

Saya tidak yakin bagaimana fetchUsersdigunakan (sebagai fungsi async?), Tetapi Anda biasanya akan menggunakan sesuatu seperti bindActionCreatorsuntuk auto-mengikat pengiriman dan kemudian Anda tidak perlu khawatir tentang menggunakan dispatchlangsung dalam komponen terhubung.

Menggunakan dispatchsemacam direktori memasangkan komponen bodoh tanpa kewarganegaraan dengan redux. Yang membuatnya kurang portabel.

Davin Tryon
sumber
3
Apa yang Anda sarankan tidak akan berhasil. Anda akan mendapatkan fetchUserssuntikan yang tidak terikat sebagai penyangga. Notasi pintasan hanya berfungsi saat Anda meneruskan objek sebagai argumen kedua. Ketika Anda melewati fungsi Anda harus memanggil bindActionCreatorsdiri sendiri: dispatch => ({ ...bindActionCreators({ fetchUsers }, dispatch), dispatch }).
Dan Abramov
Mengapa menyebarkan dan meneruskan pengiriman langsung di bindActionCreators? dispatch => ( bindActionCreators({ dispatch, fetchUsers }, dispatch))
pengguna3711421
2

Meskipun Anda dapat dispatchditurunkan sebagai bagian dari dispatchToProps, saya akan merekomendasikan untuk menghindari mengakses storeatau dispatchlangsung dari dalam komponen Anda. Sepertinya Anda akan lebih baik dilayani dengan mengirimkan pembuat tindakan terikat dalam argumen ke-2 connectdispatchToProps

Lihat contoh yang saya posting di sini https://stackoverflow.com/a/34455431/2644281 tentang cara mewariskan "pembuat tindakan yang sudah terikat" dengan cara ini komponen Anda tidak perlu mengetahui secara langsung atau bergantung pada penyimpanan / pengiriman .

Maaf singkat. Saya akan memperbarui dengan info lebih lanjut.

Erik Aybar
sumber