Saya mencoba memisahkan komponen presentasi dari komponen wadah. Saya memiliki a SitesTable
dan a SitesTableContainer
. Penampung bertanggung jawab untuk memicu tindakan redux untuk mengambil situs yang sesuai berdasarkan pengguna saat ini.
Masalahnya adalah pengguna saat ini diambil secara asinkron, setelah komponen penampung dirender pada awalnya. Ini berarti bahwa komponen penampung tidak mengetahui bahwa ia perlu menjalankan ulang kode dalam componentDidMount
fungsinya yang akan memperbarui data untuk dikirim ke SitesTable
. Saya rasa saya perlu merender ulang komponen kontainer ketika salah satu alat peraga (pengguna) berubah. Bagaimana cara melakukannya dengan benar?
class SitesTableContainer extends React.Component {
static get propTypes() {
return {
sites: React.PropTypes.object,
user: React.PropTypes.object,
isManager: React.PropTypes.boolean
}
}
componentDidMount() {
if (this.props.isManager) {
this.props.dispatch(actions.fetchAllSites())
} else {
const currentUserId = this.props.user.get('id')
this.props.dispatch(actions.fetchUsersSites(currentUserId))
}
}
render() {
return <SitesTable sites={this.props.sites}/>
}
}
function mapStateToProps(state) {
const user = userUtils.getCurrentUser(state)
return {
sites: state.get('sites'),
user,
isManager: userUtils.isManager(user)
}
}
export default connect(mapStateToProps)(SitesTableContainer);
reactjs
redux
react-redux
David
sumber
sumber
componentDidMount
akan mengubahsites
node dalam status aplikasi, yang diteruskan keSitesTable
. Node SitesStablesites
akan berubah.Jawaban:
Anda harus menambahkan kondisi dalam
componentDidUpdate
metode Anda .Contoh yang digunakan
fast-deep-equal
untuk membandingkan objek.import equal from 'fast-deep-equal' ... constructor(){ this.updateUser = this.updateUser.bind(this); } componentDidMount() { this.updateUser(); } componentDidUpdate(prevProps) { if(!equal(this.props.user, prevProps.user)) // Check if it's a new user, you can also use some unique property, like the ID (this.props.user.id !== prevProps.user.id) { this.updateUser(); } } updateUser() { if (this.props.isManager) { this.props.dispatch(actions.fetchAllSites()) } else { const currentUserId = this.props.user.get('id') this.props.dispatch(actions.fetchUsersSites(currentUserId)) } }
Menggunakan Hooks (React 16.8.0+)
import React, { useEffect } from 'react'; const SitesTableContainer = ({ user, isManager, dispatch, sites, }) => { useEffect(() => { if(isManager) { dispatch(actions.fetchAllSites()) } else { const currentUserId = user.get('id') dispatch(actions.fetchUsersSites(currentUserId)) } }, [user]); return ( return <SitesTable sites={sites}/> ) }
Jika prop Anda membandingkan adalah obyek atau array, Anda harus menggunakan
useDeepCompareEffect
bukanuseEffect
.sumber
user
perubahan? Seberapa mahal ini?ComponentWillReceiveProps()
akan dihentikan di masa mendatang karena bug dan inkonsistensi. Solusi alternatif untuk merender ulang komponen pada perubahan props adalah dengan menggunakanComponentDidUpdate()
danShouldComponentUpdate()
.ComponentDidUpdate()
dipanggil setiap kali komponen diperbarui DAN jikaShouldComponentUpdate()
mengembalikan nilai true (JikaShouldComponentUpdate()
tidak ditentukan, ia kembalitrue
secara default).shouldComponentUpdate(nextProps){ return nextProps.changedProp !== this.state.changedProp; } componentDidUpdate(props){ // Desired operations: ex setting state }
Perilaku yang sama ini dapat dicapai hanya dengan menggunakan
ComponentDidUpdate()
metode dengan menyertakan pernyataan bersyarat di dalamnya.componentDidUpdate(prevProps){ if(prevProps.changedProp !== this.props.changedProp){ this.setState({ changedProp: this.props.changedProp }); } }
Jika seseorang mencoba untuk mengatur keadaan tanpa bersyarat atau tanpa mendefinisikan
ShouldComponentUpdate()
komponen akan merender ulang tanpa batassumber
componentWillReceiveProps
akan dihentikan dan disarankan untuk tidak digunakan.Anda bisa menggunakan
KEY
kunci unik (kombinasi data) yang berubah dengan props, dan komponen itu akan dirender dengan props yang diperbarui.sumber
componentWillReceiveProps(nextProps) { // your code here}
Saya pikir itu adalah acara yang Anda butuhkan.
componentWillReceiveProps
terpicu setiap kali komponen Anda menerima sesuatu melalui props. Dari sana Anda dapat memeriksa lalu melakukan apa pun yang ingin Anda lakukan.sumber
componentWillReceiveProps
deprecated *Saya akan merekomendasikan untuk melihat jawaban saya ini, dan melihat apakah itu relevan dengan apa yang Anda lakukan. Jika saya memahami masalah Anda yang sebenarnya, Anda hanya tidak menggunakan tindakan asinkron Anda dengan benar dan memperbarui "penyimpanan" redux, yang secara otomatis akan memperbarui komponen Anda dengan alat peraga yang baru.
Bagian kode Anda ini:
componentDidMount() { if (this.props.isManager) { this.props.dispatch(actions.fetchAllSites()) } else { const currentUserId = this.props.user.get('id') this.props.dispatch(actions.fetchUsersSites(currentUserId)) } }
Seharusnya tidak memicu dalam sebuah komponen, itu harus ditangani setelah menjalankan permintaan pertama Anda.
Lihat contoh ini dari redux-thunk :
function makeASandwichWithSecretSauce(forPerson) { // Invert control! // Return a function that accepts `dispatch` so we can dispatch later. // Thunk middleware knows how to turn thunk async actions into actions. return function (dispatch) { return fetchSecretSauce().then( sauce => dispatch(makeASandwich(forPerson, sauce)), error => dispatch(apologize('The Sandwich Shop', forPerson, error)) ); }; }
Anda tidak perlu menggunakan redux-thunk, tetapi ini akan membantu Anda bernalar tentang skenario seperti ini dan menulis kode yang cocok.
sumber
makeASandwichWithSecretSauce
komponen Anda?Metode ramah untuk digunakan adalah sebagai berikut, setelah pembaruan prop, secara otomatis akan merender komponen:
render { let textWhenComponentUpdate = this.props.text return ( <View> <Text>{textWhenComponentUpdate}</Text> </View> ) }
sumber