[英]React: On which lifecycle hook should I parse new received data?
我正在嘗試解析從Firebase接收的數據,並將此新數據傳遞給組件。 數據以承諾方式異步獲取。 我遇到的問題是,即使我已經設置了componentDidMount
並調用了函數來解析那里的數據,也沒有第一次呈現它。
我從firebase收到的數據如下:
faults: [{
name: "Foo",
status: "Open"
type: "type1"
},
{
name: "Bar",
status: "Open"
type: "type2"
}],
types: [{
key: "type1",
type: "Accident"
},
{
key: "type2",
type: "Crash"
}]
正如你可以看到我需要解析的數據替換type
與正確名稱故障的types
。
為此,我有一個解析數據並設置狀態的函數。 這是該代碼:
parseFields() {
let parsedFields = [];
this.props.fields.forEach((field) => {
const typeSelected= this.props.estados.find(element => element.key === field.type) || '';
let parsedField = Object.assign({}, field);
parsedField['type'] = typeSelected.type;
parsedFields.push(parsedField);
});
this.setState({data: parsedFields});
}
在componentDidMount
和componentWillReceiveProps
上調用此函數,但是在組件裝入時,不會顯示任何數據。 但是,當組件接收到新的道具時,它將正確顯示。
難道我做錯了什么? 我也嘗試過在componentWillMount
上調用此函數,但是對於第一個渲染它不起作用。
根據要求,這是組件代碼:
import React from 'react'
import Table from './Table';
class FaultList extends React.Component {
constructor(props) {
super(props);
this.columns = [
{
name: 'Name',
field: 'name'
},
{
name: 'Type',
field: 'type'
},
{
name: 'Status',
field: 'status'
}
];
this.state = {
faults: []
};
this.parseFields = this.parseFields.bind(this);
}
parseFields() {
let parsedFields = [];
this.props.fields.forEach((field) => {
const typeSelected= this.props.types.find(element => element.key === field.type) || '';
let parsedField = Object.assign({}, field);
parsedField['type'] = typeSelected.type;
parsedFields.push(parsedField);
});
this.setState({data: parsedFields});
}
componentDidMount() {
this.parseFields();
}
componentWillReceiveProps() {
this.parseFields();
}
render() {
return(
<Table
data={this.state.faults}
columns={this.columns}
handleClick={this.props.handleClick}
/>
);
}
}
export default FaultList;
這是負責處理在父組件中處理的數據提取的代碼:
componentDidMount() {
this.faultsRef= ref.child('faults');
this.faultsRef.on('value', (snap) => {
let faults= [];
snap.forEach((child) => {
let fault= child.val();
let key = child.key;
const finalFault = update(fault, {$merge: {key}});
faults.push(finalFault);
});
this.setState({faults});
});
get('types')
.then((types) => {
this.setState({types});
});
}
get函數的代碼是:
function get(node) {
return ref.child(node).once('value')
.then((snap) => {
let list = [];
snap.forEach((child) => {
let object = child.val();
let key = child.key;
const finalObject = update(object , {$merge: {key}});
list .push(finalObject);
});
return list;
});
}
我注意到一些非常非常奇怪的事情。 如果我在父組件的“ componentDidMount”中重新排序一些代碼,然后首先檢索類型列表,然后獲取錯誤列表,則第一次重新渲染正確,但沒有解析類型,所以我我的桌子上有空單元格。
我認為您應該在Table
組件上使用this.state.data
而不是this.state.faults
:
<Table
data={this.state.data}
columns={this.columns}
handleClick={this.props.handleClick}
/>
如果我正確地理解了您的組件, FaultList
不會異步執行任何操作,而只是從父級接收道具。 鑒於此,您可以通過使FaultList
成為無狀態並僅直接解析render
的數據來簡化操作。 每當組件接收到新的道具時,組件將重新渲染(即:將調用render
),並且數據將被重新解析。
class FaultList extends React.Component {
constructor(props) {
super(props);
this.columns = [
...
];
this.parseFields = this.parseFields.bind(this);
}
// You no longer need `componentDidMount` and `componentWillReceiveProps`
parseFields() {
let parsedFields = [];
this.props.fields.forEach((field) => {
const typeSelected= this.props.types.find(element => element.key === field.type) || '';
let parsedField = Object.assign({}, field);
parsedField['type'] = typeSelected.type;
parsedFields.push(parsedField);
});
// Note: we are now returning the value instead of setting `state`.
return parsedFields;
}
render() {
return(
<Table
data={this.parseFields()}
columns={this.columns}
handleClick={this.props.handleClick}
/>
);
}
}
export default FaultList;
我發現了問題所在。 正如Bartek提到的那樣,Table組件應該引用狀態,因此我要做的就是將parseFields移動到父組件,並在每次Firebase檢索新數據時調用它。 這是該代碼:
class FaultsView extends React.Component {
constructor(props) {
super(props);
this.faultsRef = null;
this.state = {
faults: [],
parsedFaults: [],
types: []
};
this.parseFields = this.parseFields.bind(this);
}
componentDidMount() {
get('types')
.then((types) => {
this.setState({types});
});
this.faultsRef = ref.child('faults');
this.faultsRef.on('value', (snap) => {
let faults= [];
snap.forEach((child) => {
let fault= child.val();
let key = child.key;
const finalFault = update(fault, {$merge: {key}});
faults.push(finalFault);
});
this.setState({faults});
// This was the fix!
this.parseFields();
});
}
componentWillUnMount() {
this.faultsRef.off();
}
parseFields() {
let parsedFields = [];
this.props.fields.forEach((field) => {
const typeSelected= this.props.types.find(element => element.key === field.type) || '';
let parsedField = Object.assign({}, field);
parsedField['type'] = typeSelected.type;
parsedFields.push(parsedField);
});
this.setState({data: parsedFields});
}
render() {
return (
<div>
<FaultList
faults={this.state.parsedFaults}
handleClick={this.handleClick}/>
</div>
);
}
}
export default FaultsView;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.