Javascript 绑定到React组件的函数不能传递给子组件和Response

Javascript 绑定到React组件的函数不能传递给子组件和Response,javascript,reactjs,Javascript,Reactjs,我对这个背景问题感到困惑: import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; class Foo extends Component { constructor(props) { super(props) this.state = { error: false } } render() { const

我对这个背景问题感到困惑:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class Foo extends Component {
  constructor(props) {
    super(props)
    this.state = {
      error: false
    }
  }

  render() {
    const { handleChange } = this.props;
    let _handleChange = handleChange.bind(this);
    return (
      <div>
        <input type='file' onChange={_handleChange} id='input'/>
        <label htmlFor='input'> Upload </label>
        {this.state.error && <span>{this.state.errorMessage}</span>}
      </div>
    )
  }
}


class FooClosure extends Component {
  handleChange = (event) => {
    let self = this // this will always be FooClosure
    debugger // local this context will be Foo
    this.setState({ error: true, errorMessage: 'Some error happened'})
  }
  render() {
    return (
      <div>
        <Foo handleChange={this.handleChange} />
      </div>
    )
  }
}

class App extends Component {
  render() {
    return (
      <div className="App">
        <FooClosure />
      </div>
    );
  }
}

export default App;
import React,{Component}来自'React';
从“/logo.svg”导入徽标;
导入“/App.css”;
类Foo扩展组件{
建造师(道具){
超级(道具)
此.state={
错误:false
}
}
render(){
const{handleChange}=this.props;
让_handleChange=handleChange.bind(this);
返回(
上传
{this.state.error&&{this.state.errorMessage}
)
}
}
类闭包扩展组件{
handleChange=(事件)=>{
让self=this//this将始终是foo闭包
调试器//本地此上下文将是Foo
this.setState({error:true,errorMessage:'发生了一些错误'})
}
render(){
返回(
)
}
}
类应用程序扩展组件{
render(){
返回(
);
}
}
导出默认应用程序;
我正在尝试在父组件中定义的函数中设置state,该父组件绑定到子组件中。我对Javascript的理解意味着
this
将成为子组件,但是
this.setState
总是在FooClosure的上下文中执行。有人能帮我理解为什么会这样吗


我可以通过定义
handleChange=(event,self)=>…
轻松地解决这个问题,但我认为我不应该这么做

你应该这样写

class Foo extends Component {
  render() {
    return (
      <div>
        <input type='file' onChange={this.props.handleChange} id='input'/>
        <label htmlFor='input'> Upload </label>
        {this.props.error && <span>{this.props.errorMessage}</span>}
      </div>
    )
  }
}


class FooClosure extends Component {
  constructor(props) {
    super(props);
    this.state = {error: false, errorMessage: ''};
  }

  handleChange = (event) => {
    this.setState({ error: true, errorMessage: 'Some error happened'})
  }

  render() {
    return (
      <div>
        <Foo handleChange={this.handleChange.bind(this)} error={this.state.error} errorMessage={this.state.errorMessage} />
      </div>
    )
  }
}
类Foo扩展组件{
render(){
返回(
上传
{this.props.error&&{this.props.errorMessage}
)
}
}
类闭包扩展组件{
建造师(道具){
超级(道具);
this.state={error:false,errorMessage:''};
}
handleChange=(事件)=>{
this.setState({error:true,errorMessage:'发生了一些错误'})
}
render(){
返回(
)
}
}

当您在
handleChange
方法中定义
时,您明确地告诉程序查看其当前的作用域,其中函数正在编写。将其作为道具传递只会在其编写的范围内运行函数,不会重新定义
,也不会在
Foo
类中重新定义它

想象一下
FooClosure
Foo
在两个独立的房间里,不知何故成为了众生
FooClosure
能够制作比萨饼
Foo
可以调用
FooClosure
请求制作比萨饼。这里的问题是
Foo
要求
FooClosure
制作比萨饼,但是所有的配料和唯一的工作烤箱都在
Foo
的房间里

在这种情况下,最好将
handleChange
方法移动到
Foo
类中,这样
this
可以引用
Foo
而不是
FooClosure
,这反过来允许您设置
Foo
的状态

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class Foo extends Component {
  constructor(props) {
    super(props)
    this.state = {
      error: false
    }
  }

  handleChange = event => {
    this.setState({ 
      error: true, 
      errorMessage: 'Some error happened',
    })
  }

  render() {
    const { handleChange } = this
    return (
      <div>
        <input type='file' onChange={handleChange} id='input'/>
        <label htmlFor='input'> Upload </label>
        {this.state.error && <span>{this.state.errorMessage}</span>}
      </div>
    )
  }
}


class FooClosure extends Component {
  render() {
    return (
      <div>
        <Foo />
      </div>
    )
  }
}

class App extends Component {
  render() {
    return (
      <div className="App">
        <FooClosure />
      </div>
    );
  }
}

export default App;

请记住,每次在
Foo
类中发生onChange事件时,后者都会触发。

这很有帮助,但并不完全准确。问题在于,无论是通过绑定它还是将其建立为匿名函数,都无法将其恢复到Foo的新上下文中

class Foo extends Component {
  constructor(props) {
    super(props)
    this.state = {
      error: false
    }
    this.handleChange = this.props.handleChange.bind(this)
    debugger
  }

  render() {
    console.log('foo state', this.state)
    return (
      <div>
        <input type='file' onChange={this.handleChange} id='input'/>
        <label htmlFor='input'> Upload </label>
        {this.state.error && <span>{this.state.errorMessage}</span>}
      </div>
    )
  }
}


class FooClosure extends Component {
  constructor(props) {
    super(props)
    this.handleChange = this.handleChange;
  }
  handleChange() {
    let self = this // this will now be Foo
    debugger // local this context will be Foo
    this.setState({ error: true, errorMessage: 'Some error happened'})
  }
  render() {
    console.log('closure state', this.state)
    return (
      <div>
        <Foo handleChange={this.handleChange} />
      </div>
    )
  }
}
类Foo扩展组件{
建造师(道具){
超级(道具)
此.state={
错误:false
}
this.handleChange=this.props.handleChange.bind(this)
调试器
}
render(){
console.log('foo state',this.state)
返回(
上传
{this.state.error&&{this.state.errorMessage}
)
}
}
类闭包扩展组件{
建造师(道具){
超级(道具)
this.handleChange=this.handleChange;
}
handleChange(){
让self=this//this现在是Foo
调试器//本地此上下文将是Foo
this.setState({error:true,errorMessage:'发生了一些错误'})
}
render(){
console.log('closure state',this.state)
返回(
)
}
}

onChange={(event)=>this.props.handleChange.call(this,event)}onChange(event,self){…}是我找到的唯一解决方案,它是
handleChange(event,self){…}
onChange={(event)=>this.props.handleChange(event,this)}
class Foo extends Component {
  constructor(props) {
    super(props)
    this.state = {
      error: false
    }
    this.handleChange = this.props.handleChange.bind(this)
    debugger
  }

  render() {
    console.log('foo state', this.state)
    return (
      <div>
        <input type='file' onChange={this.handleChange} id='input'/>
        <label htmlFor='input'> Upload </label>
        {this.state.error && <span>{this.state.errorMessage}</span>}
      </div>
    )
  }
}


class FooClosure extends Component {
  constructor(props) {
    super(props)
    this.handleChange = this.handleChange;
  }
  handleChange() {
    let self = this // this will now be Foo
    debugger // local this context will be Foo
    this.setState({ error: true, errorMessage: 'Some error happened'})
  }
  render() {
    console.log('closure state', this.state)
    return (
      <div>
        <Foo handleChange={this.handleChange} />
      </div>
    )
  }
}