无法将undefined或null转换为反应中的对象

Jak*_*par 1 javascript firebase reactjs firebase-realtime-database

我试图从初始状态对象映射对象属性.我可以获得除嵌套之外的所有属性milesotnes.

初始状态在组件类构造函数中定义,如下所示:

class GoalView extends Component {
  constructor(props) {
    super(props);

    this.state = {
      dataGoal: {},
      uid: firebaseAuth().currentUser.uid,
      currentGoalId: this.props.match.params.goalId,
    };
  }

  componentDidMount = () => {
    const dataGoalRef = dbRef.child('goals/'+this.state.uid+'/'+this.state.currentGoalId);
    dataGoalRef.on('value', snap => {
        this.setState({
          dataGoal: snap.val(),
          currentGoalId: this.props.match.params.goalId,
        });
    });
  }

  componentWillUnmount = () => {
    this.state = {
      currentGoalId: null,
    };
  }
  
  ...
  
}
Run Code Online (Sandbox Code Playgroud)

currentGoalId从React Router V4链接获取:

<Link title="Open goal" to={"/app/goal/id"+key}>Open goal</Link>
Run Code Online (Sandbox Code Playgroud)

这是一个更高阶的组件.当前GoalView组件的render方法如下所示:

  render() {
    return(
      <div>
        <main className="content">
          <p>{this.state.dataGoal.description}</p><br /><br />

            {Object.keys(this.state.dataGoal.milestones).map( (milestoneKey) => {
              const milestonesData = this.state.dataGoal.milestones[milestoneKey];

              return <div className="milestone-wrap" key={milestoneKey}>
                       <label className="milestone-label truncate">{milestonesData.name}</label>

                     </div>
            })}

        </main>
      </div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

和国家:

在此输入图像描述

Cannot convert undefined or null to object从这一行开始{Object.keys(this.state.dataGoal.milestones).map( (milestoneKey) => {...}

但是description在该行正上方的渲染方法正好渲染.有人有想法吗?

谢谢,Jakub

May*_*kla 7

在使用之前进行Object.keys()检查dataGoal,如下所示:

this.state.dataGoal.milestones && Object.keys(this.state.dataGoal.milestones)

原因:你是从服务器获取数据,这需要时间,直到this.state.dataGoal.milestonesundefined.

或者您可以保留渲染,直到您没有使用boolin状态变量获取数据.

检查一下,它会产生同样的错误:

let a = {};

Object.keys(a.a).map(el => console.log(el));
Run Code Online (Sandbox Code Playgroud)

建议:lifecycle methods不需要绑定,直接使用,所以删除arrow function使用lifecycle methods.

  • 其余的一切都是正确的,我想建议你的另一件事(我曾经遵循),尝试使渲染方法尽可能小意味着如果你想运行一些循环来创建 ui 或其他 js 条件,请将其放在函数并在渲染中调用该函数,它将帮助您管理代码并帮助其他人了解您在做什么:) (2认同)