React – variables是未定义的而不是true / false – 组件首先被渲染?

好吧,所以我试图实现的是一个函数,它返回一个不同的标签,取决于文件是否存在,或不。 到目前为止,代码本身似乎正在工作,但顺序是错误的。 我所做的是打印出“文件存在”或“不存在”的function部分进行实际检查,将boolean保存到testvariables中,使用所述variables来确定最终返回哪个button。

现在发生了什么,即使第一部分打印出“文件确实存在”(应该保存为true ), console.log(test)进一步下降返回undefined ,这当然,导致条件不工作。

我相信我可以忽略一些非常简单的东西,但我无法弄清楚。

 import React from 'react'; import RaisedButton from 'material-ui/RaisedButton'; import fs from 'fs'; var ConfigChecker = React.createClass({ render: function(){ var test; fs.open('./App.js', 'r', (err, fd) => { if (err) { if (err.code === 'ENOENT') { console.log('file does not exist'); test = false; } throw err; } console.log('this should be executed first:'); console.log('file does exist') test = true; }); if (test) { console.log("this should be executed last:"); console.log(test); return (<RaisedButton label="true" />); } else { console.log("this should be executed last:"); console.log(test); return (<RaisedButton label="false" />); } } }); export default ConfigChecker; 

这是在dev控制台中返回的内容

asynchronous呼叫不像您认为的那样工作。 每当你看到一个函数是asynchronous的(期待一个callback函数,返回一个Promise),用“registerInterestIn {functionName}”作为函数的名字。 所以fs.open成为fs.registerInterestInOpen

考虑到这一点,你的代码现在看起来像这样:

 var test; fs.registerInterestInOpen('./App.js', 'r', ...); // Still undefined here, we just registered an interest // in the results of opening ./App.js ... nothing has // actually *happened* yet. if (test) { } else { } // And when we get down here, JavaScript will actually *do* // the opening, and call our callback with the result, when // the operating system gets back to us with the data or an error 

那么如何处理这个问题呢?

您需要使用一点React状态,以便知道组件所处的三种状态(等待查找文件是否存在,文件是否存在,文件是否存在)。 然后,您需要将callback中的状态更改为fs.open以告诉React重新呈现组件:

 const ConfigChecker = React.createClass({ getInitialState() { return { test: null }; }, componentDidMount() { fs.open('./App.js', 'r', (err, fd) => { if (err && err.code === 'ENOENT') { console.log('file does not exist'); return this.setState(() => { test: false}); } this.setState(() => { test: true}); }); }, render() { if (this.state.test == null) { return 'Loading ...'; } else { return <RaisedButton label={this.state.test} />; } } 

尝试这个:

 import React from 'react'; import RaisedButton from 'material-ui/RaisedButton'; import fs from 'fs'; var ConfigChecker = React.createClass({ getInitialState: function(){ return { test: true } }, // or componentWillMount() should work componentDidMount: function(){ var test; var self = this; fs.open('./App.js', 'r', (err, fd) => { if (err) { if (err.code === 'ENOENT') { console.log('file does not exist'); self.setState({ test: false }); // test = false; } throw err; } console.log('this should be executed first:'); console.log('file does exist') self.setState({ test: true }); // test = true; }); }, render: function(){ if (this.state.test) { console.log("this should be executed last:"); console.log(test); return (<RaisedButton label="true" />); } else { console.log("this should be executed last:"); console.log(test); return (<RaisedButton label="false" />); } }