Javascript 反应:我应该在哪个生命周期钩子上解析新接收的数据?
我试图解析从firebase接收的数据,并将新数据传递给组件。数据是通过承诺异步获取的。我遇到的问题是,它不是第一次呈现的,即使我已经设置了Javascript 反应:我应该在哪个生命周期钩子上解析新接收的数据?,javascript,reactjs,Javascript,Reactjs,我试图解析从firebase接收的数据,并将新数据传递给组件。数据是通过承诺异步获取的。我遇到的问题是,它不是第一次呈现的,即使我已经设置了componentDidMount,并调用函数来解析那里的数据 我从firebase收到的数据如下: faults: [{ name: "Foo", status: "Open" type: "type1" }, { name: "Bar", status: "Open" type: "type2" }], types: [{ k
componentDidMount
,并调用函数来解析那里的数据
我从firebase收到的数据如下:
faults: [{
name: "Foo",
status: "Open"
type: "type1"
},
{
name: "Bar",
status: "Open"
type: "type2"
}],
types: [{
key: "type1",
type: "Accident"
},
{
key: "type2",
type: "Crash"
}]
如您所见,我需要解析数据,用类型
中的正确名称替换类型
故障
为此,我有一个解析数据并设置状态的函数。以下是代码:
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});
}
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;
在componentDidMount
和componentWillReceiveProps
上调用此函数,但当组件装载时,不会显示任何数据。但是,当组件收到新道具时,它会正确显示
我做错什么了吗?我也尝试在组件willmount
上调用此函数,但在第一次渲染时它不起作用
更新
根据要求,这是部件代码:
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;
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;
});
}
更新2:
我注意到一些非常奇怪的事情。如果我对父组件的“componentDidMount”中的一段代码重新排序,首先检索类型列表,然后获取故障列表,第一次重新渲染是正确的,但是类型没有被解析,因此我的表中留下了空单元格。我认为您应该在
表组件上使用this.state.data
,而不是this.state.faults
:
<Table
data={this.state.data}
columns={this.columns}
handleClick={this.props.handleClick}
/>
如果我正确理解了您的组件,故障列表
不会异步执行任何操作,只会从父级接收道具。有鉴于此,您可以通过将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;
类故障列表扩展了React.Component{
建造师(道具){
超级(道具);
此值为。列=[
...
];
this.parseFields=this.parseFields.bind(this);
}
//您不再需要'componentDidMount'和'componentWillReceiveProps'`
parseFields(){
让parsedFields=[];
this.props.fields.forEach((字段)=>{
const typeSelected=this.props.types.find(element=>element.key==field.type)| |“”;
让parsedField=Object.assign({},field);
parsedField['type']=typeSelected.type;
parsedFields.push(parsedField);
});
//注意:我们现在返回的是值,而不是设置“state”。
返回解析字段;
}
render(){
返回(
);
}
}
导出默认故障列表;
我找到了问题所在。如前所述,Table组件应该有一个对status的引用,所以我所要做的就是将parseFields移动到父组件,并在firebase每次检索新数据时调用它。以下是代码:
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});
}
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;
class FaultsView扩展了React.Component{
建造师(道具){
超级(道具);
this.faultsRef=null;
此.state={
故障:[],
解析的故障:[],
类型:[]
};
this.parseFields=this.parseFields.bind(this);
}
componentDidMount(){
获取('类型')
。然后((类型)=>{
this.setState({types});
});
this.faultsRef=ref.child('faults');
this.faultsRef.on('value',(snap)=>{
设错误=[];
snap.forEach((子项)=>{
让fault=child.val();
让key=child.key;
const finalFault=update(错误,{$merge:{key}});
故障。推送(最终故障);
});
this.setState({faults});
//这就是解决办法!
这是parseFields();
});
}
组件将卸载(){
this.faultsRef.off();
}
parseFields(){
让parsedFields=[];
this.props.fields.forEach((字段)=>{
const typeSelected=this.props.types.find(element=>element.key==field.type)| |“”;
让parsedField=Object.assign({},field);
parsedField['type']=typeSelected.type;
parsedFields.push(parsedField);
});
this.setState({data:parsedFields});
}
render(){
返回(
);
}
}
导出默认故障视图;
您可以发布您的组件代码吗?具体来说,您应该在某处使用this.state.data
。我已经更新了问题。抱歉耽搁了,因为我必须翻译代码。是的,这解决了第一次重新渲染的问题,但我需要在渲染之前解析数据。也许我没有在正确的生命周期中进行解析。也许我可以用解析后的数据覆盖状态,但我认为这不是正确的解决方案。所以在重新渲染之后,一切都好吗?问题只出现在初始渲染时?这不是暗示您的类型
数据是异步获取的,所以当组件第一次呈现时,类型
还没有被获取吗?是的,这是问题的一部分。关键是通过从父组件接收的道具解析FaultList上的字段。有关更多信息,请参阅已接受的答案。谢谢对这就是我要找的!我找到了另一份工作,但我更喜欢你的答案!非常感谢D