想象下面某个组件的功能:
handleInputChange(e) { // let val = e.target.value; - if I uncomment this, it works. // Update text box value this.setState(function (prevState, props) { return { searchValue: e.target.value, } }) }
和文本框,由上述组件的子组件呈现,并接收handleInputChange为props:
handleInputChange
props
<input type="text" onChange={that.props.handleInputChange} value={that.props.searchValue} />
当我在文本字段中输入内容时,出现错误消息Cannot read property 'value' of null。
Cannot read property 'value' of null
如果我取消注释handleInputChange函数中的第一行(将文本框值存储在val变量中),那么它将很好地工作。想法为什么?
val
这是因为React进行了事件池 -回调完成后,所有事件的字段都为空,因此您在异步setState回调中将它们视为null 。
setState
请将事件数据复制到变量或调用event.persist()以禁用此行为。
event.persist()
handleInputChange(e) { e.persist(); this.setState(function (prevState, props) { return { searchValue: e.target.value, } }) }
要么:
handleInputChange(e) { const val = e.target.value; this.setState(function (prevState, props) { return { searchValue: val } }) }
请参见以下示例:
class Example extends React.Component { constructor() { super() this.state = { } } handleInputChangeCopy = (e) => { const val = e.target.value; console.log('in callback'); console.log(e.target.value); this.setState(function (prevState, props) { console.log('in async callback'); console.log(val); return { searchValue: val } }) } handleInputChangePersist = (e) => { e.persist(); console.log('in callback'); console.log(e.target.value); this.setState(function (prevState, props) { console.log('in async callback'); console.log({ isNull: e.target === null }) console.log(e.target.value); return { searchValue: e.target.value } }) } handleInputChange = (e) => { console.log('in callback'); console.log(e.target.value); this.setState(function (prevState, props) { console.log('in async callback'); console.log({ isNull: e.target === null }) console.log({ event: e }); console.log(e.target.value); return { searchValue: e.target.value } }) } render() { return ( <div> <div>Copy example</div> <input type="text" onChange={this.handleInputChangeCopy} /> <p>Persist example</p> <input type="text" onChange={this.handleInputChangePersist} /> <p>Original example - please note nullified fields of the event in the async callback. <small>Breaks the example, please re-run after a Script error</small></p> <input type="text" onChange={this.handleInputChange} /> <div style={{height: 300}} /> </div> ) } } ReactDOM.render( <Example searchValue={"test"} />, document.getElementById('app') ) <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="app"></div>