Javascript 反应:我应该在哪个生命周期钩子上解析新接收的数据?

Javascript 反应:我应该在哪个生命周期钩子上解析新接收的数据?,javascript,reactjs,Javascript,Reactjs,我试图解析从firebase接收的数据,并将新数据传递给组件。数据是通过承诺异步获取的。我遇到的问题是,它不是第一次呈现的,即使我已经设置了componentDidMount,并调用函数来解析那里的数据 我从firebase收到的数据如下: faults: [{ name: "Foo", status: "Open" type: "type1" }, { name: "Bar", status: "Open" type: "type2" }], types: [{ k

我试图解析从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"
}]
如您所见,我需要解析数据,用
类型
中的正确名称替换
类型
故障

为此,我有一个解析数据并设置状态的函数。以下是代码:

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