Saya akan mengaturnya sehingga Anda mengandalkan variabel kondisi global untuk memberi tahu komponen Anda kapan harus merender. Redux lebih baik untuk skenario ini di mana banyak komponen berbicara satu sama lain, dan Anda menyebutkan dalam komentar bahwa Anda kadang-kadang menggunakannya. Jadi saya akan membuat sketsa jawaban menggunakan Redux.
Anda harus memindahkan panggilan API ke wadah induk, Component A
,. Jika Anda ingin agar cucu-cucu Anda render hanya setelah panggilan API selesai, Anda tidak dapat menyimpan panggilan API itu sendiri di cucu. Bagaimana panggilan API dapat dibuat dari komponen yang belum ada?
Setelah semua panggilan API dilakukan, Anda dapat menggunakan tindakan untuk memperbarui variabel status global yang berisi banyak objek data. Setiap kali data diterima (atau kesalahan ditangkap), Anda dapat mengirim tindakan untuk memeriksa apakah objek data Anda terisi penuh. Setelah sepenuhnya terisi, Anda dapat memperbarui loading
variabel ke false
, dan membuat Anda kondisionalGrid
komponen .
Jadi misalnya:
// Component A
import { acceptData, catchError } from '../actions'
class ComponentA extends React.Component{
componentDidMount () {
fetch('yoururl.com/data')
.then( response => response.json() )
// send your data to the global state data array
.then( data => this.props.acceptData(data, grandChildNumber) )
.catch( error => this.props.catchError(error, grandChildNumber) )
// make all your fetch calls here
}
// Conditionally render your Loading or Grid based on the global state variable 'loading'
render() {
return (
{ this.props.loading && <Loading /> }
{ !this.props.loading && <Grid /> }
)
}
}
const mapStateToProps = state => ({ loading: state.loading })
const mapDispatchToProps = dispatch => ({
acceptData: data => dispatch( acceptData( data, number ) )
catchError: error=> dispatch( catchError( error, number) )
})
// Grid - not much going on here...
render () {
return (
<div className="Grid">
<GrandChild1 number={1} />
<GrandChild2 number={2} />
<GrandChild3 number={3} />
...
// Or render the granchildren from an array with a .map, or something similar
</div>
)
}
// Grandchild
// Conditionally render either an error or your data, depending on what came back from fetch
render () {
return (
{ !this.props.data[this.props.number].error && <Your Content Here /> }
{ this.props.data[this.props.number].error && <Your Error Here /> }
)
}
const mapStateToProps = state => ({ data: state.data })
Peredam Anda akan memegang objek negara global yang akan mengatakan apakah semuanya siap untuk pergi atau belum:
// reducers.js
const initialState = {
data: [{},{},{},{}...], // 9 empty objects
loading: true
}
const reducers = (state = initialState, action) {
switch(action.type){
case RECIEVE_SOME_DATA:
return {
...state,
data: action.data
}
case RECIEVE_ERROR:
return {
...state,
data: action.data
}
case STOP_LOADING:
return {
...state,
loading: false
}
}
}
Dalam tindakan Anda:
export const acceptData = (data, number) => {
// First revise your data array to have the new data in the right place
const updatedData = data
updatedData[number] = data
// Now check to see if all your data objects are populated
// and update your loading state:
dispatch( checkAllData() )
return {
type: RECIEVE_SOME_DATA,
data: updatedData,
}
}
// error checking - because you want your stuff to render even if one of your api calls
// catches an error
export const catchError(error, number) {
// First revise your data array to have the error in the right place
const updatedData = data
updatedData[number].error = error
// Now check to see if all your data objects are populated
// and update your loading state:
dispatch( checkAllData() )
return {
type: RECIEVE_ERROR,
data: updatedData,
}
}
export const checkAllData() {
// Check that every data object has something in it
if ( // fancy footwork to check each object in the data array and see if its empty or not
store.getState().data.every( dataSet =>
Object.entries(dataSet).length === 0 && dataSet.constructor === Object ) ) {
return {
type: STOP_LOADING
}
}
}
Ke samping
Jika Anda benar-benar menikah dengan gagasan bahwa panggilan API Anda tinggal di dalam masing-masing cucu, tetapi bahwa seluruh Kotak cucu tidak memberikan hingga semua panggilan API selesai, Anda harus menggunakan solusi yang sama sekali berbeda. Dalam hal ini, cucu Anda harus diberikan dari awal untuk melakukan panggilan, tetapi memiliki kelas css display: none
, yang hanya berubah setelah variabel keadaan global loading
ditandai sebagai salah. Ini juga bisa dilakukan, tetapi semacam selain dari React.