【问题标题】:How do you pass an onClick function to grandchild component in React?如何将 onClick 函数传递给 React 中的孙子组件?
【发布时间】:2021-07-29 13:38:04
【问题描述】:

我刚刚开始使用 React,并针对我的案例调整了井字游戏教程。 我正在尝试单击孙组件以更改祖父组件的状态。代码如下:

class App extends React.Component {
  
  constructor(props) {
    super(props);
    this.state = {
      fields: [
        {
          id: 1,
          show: false
        },
        {
          id: 2,
          show: false
        }
      ]
    }
  }

  handleClick(i) {
    const fields = this.state.fields.slice();
    fields[i].show = true;
    this.setState({fields: fields});
  }
  
  render() {return <Preview />}
      
}

const Preview = (props) => {
  
  return (
    <div className="preview">
      {props.fields.map((field) => (
        <Field data={field} key={field.id} onClick={ props.onClick(field.id) }/>
      ))}
    </div>
  );
};

const Field = props => {
  
  return (
    <div className="field" onClick={ props.onClick } />
  );
};

我得到一个 TypeError: Cannot read property 'state' of undefined from this line:

handleClick(i) {
const fields = this.state.fields.slice();

【问题讨论】:

  • 但是您没有将任何道具传递给&lt;Preview /&gt;

标签: javascript reactjs


【解决方案1】:

问题

  1. App 类的 this 未绑定到 handleClick 函数。这是TypeError: Cannot read property 'state' of undefined 错误的原因。
  2. 您正在改变您的状态对象。对数组进行切片会创建一个新的数组引用,但 fields[i].show = true; 会改变状态中的对象引用。
  3. 您没有将 fieldsonClick 属性传递给 Preview
  4. onClick 回调在 Preview 中未正确调用。

解决方案

  1. this 绑定到处理程序或转换为箭头函数以便自动绑定。

    constructor(props){
      ...
      this.handleClick = this.handleClick.bind(this);
    }
    

    handleClick = (i) => { ..... };
    
  2. 不要改变状态。浅拷贝状态然后更新属性。

    handleClick = (id) => {
      this.setState(prevState => ({
        fields: prevState.fields.map((field) => {
          return field.id === id ? {
            ...field,
            show: true,
          } : field;
        }),
      }));
    };
    
  3. fieldshandleClick 作为onClick 传递给Preview

    render() {
      return (
        <Preview
          fields={this.state.fields}
          onClick={this.handleClick}
        />
      );
    }
    
  4. 使用 id 正确调用 props.onClick

    {props.fields.map((field) => (
      <Field
        data={field}
        key={field.id}
        onClick={() => props.onClick(field.id)}
      />
    ))}
    

【讨论】:

    【解决方案2】:

    我已经添加了一些解释,检查 cmets

      // [...]
    
      render() {
        // Here you need to pass "fields" and "handleClick" as props:
        return <Preview fields={this.state.fields} onClickField={this.handleClick} />
      }
          
    }
    
    const Preview = (props) => {
      // Here you get the props:
      const { fields, onClickField } = props;
    
      // Your onclick was a function call instead of just a function
      return (
        <div className="preview">
          {fields.map((field) => (
            <Field 
              data={field}
              key={field.id}
              onClick={() => onClickField(field.id) }
            />
          ))}
        </div>
      );
    };
    
    const Field = props => {
      
      return (
        <div className="field" onClick={ props.onClick } />
      );
    };
    

    【讨论】:

      猜你喜欢
      • 2021-09-17
      • 1970-01-01
      • 2021-09-30
      • 2021-06-10
      • 2019-12-31
      • 1970-01-01
      • 2021-12-28
      • 2017-06-18
      • 1970-01-01
      相关资源
      最近更新 更多