繁体   English   中英

绑定到 React 组件的函数无法传递给子组件并反弹

[英]Function bound to React Component Cannot Be Passed to Child Component and Rebound

我在这个上下文问题上遇到了麻烦:

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;

我正在尝试在父组件中定义的函数内使用 setState,该函数被绑定在子组件中。 我对 Javascript 的理解意味着this将成为子组件,但this.setState始终在 FooClosure 的上下文中执行。 谁能帮我理解为什么会这样?

我可以通过定义handleChange = (event, self) => ...轻松解决这个问题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>
    )
  }
}

当您在handleChange方法中定义this时,您明确地告诉程序查看正在编写函数的当前范围。 将它作为 prop 传递只会在其书面范围内运行该函数,而不是重新定义this ,在你的Foo类中重新定义它也不会被证明是有帮助的。

想象一下FooClosureFoo在两个不同的房间里,不知何故变成了有情众生。 FooClosure可以制作比萨饼。 Foo可以调用FooClosure并要求制作比萨饼。 这里的问题是Foo要求FooClosure制作比萨饼,但所有原料和唯一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;

现在这当然会使您的FooClosure类变得多余。 如果您需要根据Foo中的 onChange 处理任何事情,您可以使用:

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 => {
    const { handleFooClosureMethod } = this.props.handleFooClosureMethod
    handleFooClosureMethod(args)
    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 {
  handleChange = args => {
    //handle this method
  }
  render() {
    return (
      <div>
        <Foo handleFooClosureMethod={this.handleChange} />
      </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>
    )
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM