Tôi sẽ thiết lập nó để bạn dựa vào một biến trạng thái toàn cầu để cho biết các thành phần của bạn khi nào sẽ kết xuất. Redux tốt hơn cho kịch bản này khi nhiều thành phần đang nói chuyện với nhau và đôi khi bạn đã đề cập trong một nhận xét rằng đôi khi bạn sử dụng nó. Vì vậy, tôi sẽ phác thảo một câu trả lời bằng Redux.
Bạn sẽ phải chuyển các lệnh gọi API của mình sang vùng chứa cha , Component A
. Nếu bạn muốn cho cháu của mình kết xuất chỉ sau khi các lệnh gọi API hoàn tất, bạn không thể giữ các cuộc gọi API đó cho chính các cháu của mình. Làm thế nào một cuộc gọi API có thể được thực hiện từ một thành phần chưa tồn tại?
Khi tất cả các lệnh gọi API được thực hiện, bạn có thể sử dụng các hành động để cập nhật biến trạng thái toàn cục có chứa một loạt các đối tượng dữ liệu. Mỗi khi dữ liệu được nhận (hoặc một lỗi được bắt gặp), bạn có thể gửi một hành động để kiểm tra xem đối tượng dữ liệu của bạn đã được điền đầy đủ chưa. Khi nó được điền đầy đủ, bạn có thể cập nhật một loading
biến false
và hiển thị có điều kiện Grid
thành phần của bạn .
Ví dụ:
// 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 })
Trình giảm tốc của bạn sẽ giữ đối tượng trạng thái toàn cầu sẽ cho biết mọi thứ đã sẵn sàng hay chưa:
// 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
}
}
}
Trong hành động của bạn:
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
}
}
}
Qua một bên
Nếu bạn thực sự kết hôn với ý tưởng rằng các cuộc gọi API của bạn sống bên trong mỗi đứa cháu, nhưng toàn bộ Lưới cháu không kết xuất cho đến khi tất cả các lệnh gọi API được hoàn thành, bạn phải sử dụng một giải pháp hoàn toàn khác. Trong trường hợp này, cháu của bạn sẽ phải được kết xuất ngay từ đầu để thực hiện cuộc gọi của chúng, nhưng có một lớp css với display: none
, chỉ thay đổi sau khi biến trạng thái toàn cầu loading
được đánh dấu là sai. Điều này cũng có thể thực hiện được, nhưng bên cạnh quan điểm của React.