Javascript reactjs:无法映射到状态,因为它未定义/错误

Javascript reactjs:无法映射到状态,因为它未定义/错误,javascript,reactjs,Javascript,Reactjs,我无法映射我的状态,无法传递给我的孙子EmailDetails。在我尝试在EmailDetails的渲染功能中映射URL数组之前,我可以将其登录到控制台 import React, { Component } from "react"; import IssueBox from "./issuebox.js"; import "./App.css"; class App extends Component { constructor(props) {

我无法映射我的状态,无法传递给我的孙子
EmailDetails
。在我尝试在
EmailDetails
的渲染功能中映射URL数组之前,我可以将其登录到控制台

 import React, { Component } from "react";
    import IssueBox from "./issuebox.js";
    import "./App.css";

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

        this.state = {
          isLoaded: false,
          emails: [],
          counter: 0,
          title: "Test run",
          value: "",
          selectedEmailId: 0,
          currentSection: "inbox"
        };
      }

      componentDidMount() {
        fetch("blah")
          .then(res => res.json())
          .then(result => {
            const emails = result.data;
            console.log("resutl state: ", emails);
            let id = 0;
            for (const email of emails) {
              email.id = id++;
            }
            this.setState({
              isLoaded: true,
              emails: emails
            });
          });
      }

      handleClickReproducibleCounter(e) {
        let count = this.state.increment
          ? this.state.count + 1
          : this.state.count - 1;

        let increment = this.state.increment;

        if (count === 0) {
          increment = true;
        } else if (count >= 2) {
          increment = false;
        }

        this.setState({
          count,
          increment
        });
      }

      render() {
        return (
          <div className="App">
            <div>
              emails={this.state.emails}
              selectedEmailId={this.state.selectedEmailId}
              onEmailSelected={id => {
                this.openEmail(id);
              }}
              handleClickReproducibleCounter={this.handleClickReproducibleCounter}
            </div>
          </div>
        );
      }
    }
//issuebox.js

import React, { Component } from "react";
import "./App.css";
import EmailDetails from "./emailDetails";

class IssueBox extends Component {
  constructor(args) {
    super(args);
  }

  render() {

    const currentEmail = this.props.emails.find(
      x => x.id === this.props.selectedEmailId
    );
    console.log("emailDetail view: ", currentEmail); // email obj is present

    return (
      <div className="wrapper">
        <div className="inbox-container">
          <EmailList
            emails={this.props.emails}
            onEmailSelected={this.props.onEmailSelected}
            selectedEmailId={this.props.selectedEmailId}
          />

          <EmailDetails
            email={currentEmail} 
            onReproducibleCounter={this.props.handleClickReproducibleCounter}
            onValidateSumbit={this.props.handleClickValidateSumbission}
            handleTextInputChange={this.props.handleTextInputChange}
          />
        </div>
      </div>
    );
  }
}

export default IssueBox;
import React,{Component}来自“React”;
导入“/App.css”;
从“/EmailDetails”导入EmailDetails;
类IssueBox扩展组件{
构造函数(args){
超级(args);
}
render(){
const currentEmail=this.props.emails.find(
x=>x.id==this.props.selectedEmailId
);
log(“emailDetail视图:”,currentEmail);//存在电子邮件对象
返回(
);
}
}
出口默认发行箱;
//电子邮件详细信息

import React, { Component } from "react";
import "./App.css";

class EmailDetails extends Component {
  constructor(args) {
    super(args);

    this.state = {
      counter: "",
      email: []
    };
  }

  componentDidUpdate(prevProps) {
    if (this.props.email !== prevProps.email) {
      this.setState({ email: this.props.email });
    }
  }

  render() {
    const currentEmail = this.state.email;
    console.log(currentEmail, this.state.email.urls); // able to console obj
    const test = this.state.email.urls.map(obj => {
      //error occurs here
      console.log(obj);
    });
    return (
      <div className="email-content">
        <div className="email-content__header">
          <h3 className="email-content__subject">Issue</h3>
          <div className="email-content__from">Group:</div>
        </div>
        <div className="email-content__message">
          <table role="table">
            <thead role="rowgroup">
              <tr role="row">
                <th role="columnheader">Searched URL</th>
                <th role="columnheader">Error URL</th>
                <th role="columnheader">NR</th>
                <th role="columnheader">Task</th>
              </tr>
            </thead>
            <tbody role="rowgroup" className="group-row" />
          </table>
        </div>

      </div>
    );
  }
}

export default EmailDetails;
import React,{Component}来自“React”;
导入“/App.css”;
类EmailDetails扩展组件{
构造函数(args){
超级(args);
此.state={
柜台:“,
电子邮件:[]
};
}
componentDidUpdate(prevProps){
如果(this.props.email!==prevProps.email){
this.setState({email:this.props.email});
}
}
render(){
const currentEmail=this.state.email;
console.log(currentmail,this.state.email.url);//能够控制台obj
const test=this.state.email.url.map(obj=>{
//这里发生错误
控制台日志(obj);
});
返回(
问题
组:
搜索的URL
错误URL
天然橡胶
任务
);
}
}
导出默认电子邮件详细信息;

将此作为我的出发点:

希望我理解您的问题,当您向孩子们传递这样的回调时,您需要确保
this
关键字指向正确的内容

最简单的方法是使用函数

 handleClickReproducibleCounter(e) {
变成

 handleClickReproducibleCounter = e => {
您还可以在
构造函数中通过添加一行

this.handleClickReproducibleCounter = this.handleClickReproducibleCounter.bind(this)
这样做的目的是确保在调用
handleClickRegenerativeCounter
时,
this.state
始终引用父组件的状态(或它绑定到的任何组件)

关于你的问题:

这是否意味着我需要跟踪孙辈的另一个状态


正确,您不需要这样做。只要回调被正确绑定到父组件状态,您就可以将其向下传递,并且您可以在应用程序中的任何位置更改该状态。

我本来打算写一条评论,但时间变长了,所以我决定提供一个答案

这是一个有点难遵循您的代码,但有一些问题,我看到和一些事情,我不明白

首先,您没有在
App
中绑定您的
handleclickrepreseaturalcounter
。因此,不能对回调函数使用
this
。要么在构造函数中绑定它,要么改用arrow函数

handleClickReproducibleCounter = (e) => {
...
}
其次,您在
EmailDetails
组件中使用此功能,如:

<button onClick={this.props.onReproducibleCounter(obj.id)}>
不过,在JSX道具中使用箭头函数或绑定函数并不太好,因为它们会在每次渲染中重新创建。但是,在你的情况下,改变这种逻辑有点棘手。您正在将道具传递给子组件,并在那里映射一些东西。简单的方法是,在父组件中映射,然后将单个项传递给子组件

现在,我不明白的事情。您正在向回调传递一些
obj.id
,但正在等待
e
?在函数中似乎没有使用这个参数

我不明白的第二件事是,在你的映射中,你正在使用第二个参数作为
onrepreseatedcounter

email.urls.map((obj, onReproducibleCounter) => {
第二个参数是
index

评论后更新

您正在使用异步作业在父级中获取此数据。当您尝试映射
this.state.email.url
时,此时没有
this.state.email.url
,则会出现错误

只需使用条件渲染或日志记录即可

(this.state.email.urls || [] ).map(obj => {
      //error occurs here
    console.log(obj);
});
因此,如果没有
email.url
,那么我们的地图将使用一个空数组,这对我们来说是合适的。获取完成后,组件将重新呈现,它将映射真实数据

但是,不要把你的道具变成孩子的状态。使用那里的
电子邮件
道具。如果您需要对它执行某些操作,请在您的子组件中执行

下面是一个非常简单而愚蠢的例子:

const Child=(道具)=>{
常数doSomething=()=>{
const newNumber=props.number*20;
道具。手柄编号(新编号);
}
返回(
点击我,在孩子身上做点什么,改变这个数字。
);
}
类应用程序扩展了React.Component{
状态={
编号:10,
}
handleNumber=number=>this.setState({number});
render(){
返回
编号为:{this.state.Number}

; } } render(,document.getElementById(“根”))


感谢您指出我的错误。我确实在那里迷路了。我有一个后续问题:在填充日志之前,它将我的日志注册为
undefined undefined
,这有一个短暂的延迟,我应该使用哪个生命周期挂钩?不客气。您是否要求
电子邮件.url.map
?如果是的话,我将更新我的答案。我添加了一个简单的例子。你有错误吗?如果是这样的话,是什么原因造成的?我确实得到了一个错误:
在调用this.state.email.url.map()时,无法在呈现函数中读取EmailDetails中未定义的属性“map”
,该行代码不会出现在您发布的内容中的任何地方。请输入您的代码以显示它。另外,显示一个示例值
email.urls.map((obj, onReproducibleCounter) => {
(this.state.email.urls || [] ).map(obj => {
      //error occurs here
    console.log(obj);
});