【问题标题】:Can't call setState无法调用 setState
【发布时间】:2019-08-30 22:04:11
【问题描述】:

我不得不在我的 react 应用程序中将我的代码从使用 fetch 更改为 require 以便在电子中使用。由于这样做,我得到了以下错误:

警告:无法在尚未安装的组件上调用 setState。 这是一个无操作,但它可能表明您的应用程序中存在错误。 相反,直接分配给this.state 或定义state = {}; 在 App 组件中具有所需状态的类属性。

我了解为什么我收到此错误,但我不知道如何根据我当前的代码解决此问题。我也很困惑为什么从 fetch 移动到 require 时会发生这种情况。

当前代码:

constructor(props) {
    super(props);
    this.state={
      config:{
        nlinks:[],
        },
        numPages: null,
        pageNumber: 1,
      popup: null,
      pdf:null,
      homelhs:"",
      homerhs:"",
      currentNlink:0,
      currentClink:0,

      };

      const json = require('../public/config.json');
      for (var n=0 ; n<json.nlinks.length ; n++)
      {
        json.nlinks[n].state = (n===0?1:0); // create state field dynamically
        json.nlinks[n].currentChapter = 0; // create field dynamically
        if (json.nlinks[n].chapters)
        {
          if (!json.nlinks[n].test) json.nlinks[n].test={state:0,submitted:0,title:"dummy",questions:[]}; // create dummy test dynamically
          for (var q=0 ; q<json.nlinks[n].test.questions.length ; q++)
          {
            json.nlinks[n].test.questions[q].response=0;
            json.nlinks[n].test.questions[q].correct=false;
          }
          for(var c=0 ; c<json.nlinks[n].chapters.length ; c++)
          {
            json.nlinks[n].chapters[c].state = (c===0?1:0); // create state field dynamically
            if (json.nlinks[n].chapters[c].sections)
            {
              json.nlinks[n].chapters[c].currentSection=0; 
              for (var s=0 ; s<json.nlinks[n].chapters[c].sections.length ; s++)
              {
                json.nlinks[n].chapters[c].sections[s].state = (s===0?1:0); // create state field dynamically
              }
            }
            else
            {
              json.nlinks[n].chapters[c].sections=[];
            }
          }
        }
        else
        {
          json.nlinks[n].chapters=[];
        }
      }
      this.setState({config: json,});

      this.handleSubmit=this.handleSubmit.bind(this);
//      this.handleChange=this.handleChange.bind(this);

    }

原代码:

constructor(props) {
    super(props);
    this.state={
      config:{
        nlinks:[],
        },
        numPages: null,
        pageNumber: 1,
      popup: null,
      pdf:null,
      homelhs:"",
      homerhs:"",
      currentNlink:0,
      currentClink:0,

      };


      fetch('config.json')
        .then((r) => r.json())
        .then((json) =>{
          //console.log(json);
          //json defines the module NavLink s and their content - so save it to App state
          for (var n=0 ; n<json.nlinks.length ; n++)
          {
            json.nlinks[n].state = (n===0?1:0); // create state field dynamically
            json.nlinks[n].currentChapter = 0; // create field dynamically
            if (json.nlinks[n].chapters)
            {
              if (!json.nlinks[n].test) json.nlinks[n].test={state:0,submitted:0,title:"dummy",questions:[]}; // create dummy test dynamically
              for (var q=0 ; q<json.nlinks[n].test.questions.length ; q++)
              {
                json.nlinks[n].test.questions[q].response=0;
                json.nlinks[n].test.questions[q].correct=false;
              }
              for (var c=0 ; c<json.nlinks[n].chapters.length ; c++)
              {
                json.nlinks[n].chapters[c].state = (c===0?1:0); // create state field dynamically
                if (json.nlinks[n].chapters[c].sections)
                {
                  json.nlinks[n].chapters[c].currentSection=0; 
                  for (var s=0 ; s<json.nlinks[n].chapters[c].sections.length ; s++)
                  {
                    json.nlinks[n].chapters[c].sections[s].state = (s===0?1:0); // create state field dynamically
                  }
                }
                else
                {
                  json.nlinks[n].chapters[c].sections=[];
                }
              }
            }
            else
            {
              json.nlinks[n].chapters=[];
            }
          }
          this.setState({config: json,});

          });

      this.handleSubmit=this.handleSubmit.bind(this);
//      this.handleChange=this.handleChange.bind(this);

}

link to full app.js

Render() { } 内我正在尝试以下操作:

if (this.state.homerhs==='')
          {
            fs.readFile('resources/app.asar/build/pages/home.rhs.html', 'utf8', function(err, homerhsrequire) {
              console.log(err);
              console.log(homerhsrequire);
              homerhsrequire=homerhsrequire.replace(/src="/g,'src="./pages/');
              homerhsrequire=homerhsrequire.replace(/src='/g,"src='./pages/");
              //this.setState({homerhs:homerhsrequire});
              this.state.homerhs = homerhsrequire;
            });       

          }

但是这会返回:

App.js:708 Uncaught TypeError: Cannot read property 'state' of 未定义

【问题讨论】:

  • 可以分享完整的组件代码吗?我们需要它才能给您答复。无论如何,当你在构造函数中时,你应该直接赋值给this.state,而不是使用this.setState
  • 添加指向 gist 文件的链接

标签: reactjs fetch state require fs


【解决方案1】:

不要在构造函数中调用 this.setState() 并将 fetch 调用移动到 componentDidMount lifecylce 方法。 https://reactjs.org/docs/faq-ajax.html

【讨论】:

    【解决方案2】:

    this.setState 在构造函数中不可用 - 在构造函数中使用 this.state

    最佳做法是在componentDidMount 中使用任何类型的获取。理想情况下,你应该有一些 redux 逻辑并在一个动作中进行获取 - 这样你就可以将你的组件与一些 redux 状态属性连接起来,这些属性是由于调用 fetch 调用的动作而设置的。

    【讨论】:

    • 我在与我的componentDidMount 相同的组件中有一个函数(fetchHTML),其中有一个提取。我无法将此功能移至componentDidMount,而且我不熟悉redux。有没有办法可以将state 数据传回componentDidMount,但将我的fs.readFile 保留在它自己的函数fetchHTML 中?
    • 可以通过 this.state 访问 componentDidMount 中的状态。这能回答问题吗?
    • 我刚刚尝试过这样做,但是我得到了:App.js:774 Uncaught TypeError: Cannot read property 'state' of undefined
    • 我已经用我上面提到的示例更新了这个问题
    猜你喜欢
    • 1970-01-01
    • 2021-06-08
    • 2019-09-21
    • 2019-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-15
    • 2018-11-19
    相关资源
    最近更新 更多