简体   繁体   English

反应 - 向下传递 state

[英]React - passing state down

I am building a CV creator in React.我正在 React 中构建一个简历创建者。 I have a form, a preview component and their closest parent component is Main.我有一个表单,一个预览组件,它们最接近的父组件是 Main。 What I want to achieve is that when a user is typing inside form fields, the preview fields on the right get automatically updated with data from form but I just can't get it to work.我想要实现的是,当用户在表单字段中输入时,右侧的预览字段会使用表单中的数据自动更新,但我无法让它工作。 This is my first project in React, and I cannot use hooks or functional components.这是我在 React 中的第一个项目,我不能使用钩子或函数组件。 I know that I am doing something wrong, but cannot pinpoint what.我知道我做错了什么,但无法确定是什么。

Main component主要成分

import React, { Component } from "react";
import Form from "./form/Form";
import Preview from "./formpreview/Preview";

class Main extends Component {
  constructor(props) {
    super(props);
    this.state = {
      firstName: "",
      lastName: "",
      title: "",
      address: "",
      phoneNum: "",
      email: "",
      description: "",
    };

    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleInputChange = this.handleInputChange.bind(this);
  }

  handleSubmit = (event) => {
    event.preventDefault();
  };

  handleInputChange = (event) => {
    this.setState = {
      [event.target.name]: event.target.value,
    };
  };

  render() {
    const { firstName } = this.state;
    return (
      <div className="main">
        <Form
          submitForm={this.handleSubmit}
          changeInput={this.handleInputChange}
          firstName={firstName} lastName={lastName} title= 
          {title} address={address} phoneNum={phoneNum}
          email={email} description={description}
        />
        <Preview onChange={this.handleInputChange} 
         firstName={firstName} lastName={lastName} title= 
          {title} address={address} phoneNum={phoneNum}
          email={email} description={description}/>
      </div>
    );
  }
}

Form component表单组件

import React, { Component } from "react";
import Personal from './buildingblocks/PersonalInfo';
import Experience from './buildingblocks/Experience';
import Education from './buildingblocks/Education';
import Buttons from './buildingblocks/FormButtons';

class Form extends Component {
   constructor(props) {
     super(props);
     this.state = {
       firstName: this.props.firstName,
       lastName: this.props.lastName,
       title: this.props.title,
       address: this.props.address,
       phoneNum: this.props.phoneNum,
       email: this.props.email,
       description: this.props.description
     }
   }

   submitForm = () => {
     this.props.submitForm()
   }

   changeInput = () => {
     this.props.changeInput()
   }

  
  render() {
    const {firstName, lastName, title, address, phoneNum, email, description} = this.state;
  
    return (
        <form className="cvForm" onSubmit={this.submitForm} onChange={this.changeInput}>
          <Personal firstName={firstName} lastName={lastName} title={title} address={address} phoneNum={phoneNum} email={email} description={description}/>

          <Experience />

          <Education />

          <Buttons />

        </form>
    );
  }
}

export default Form;

Preview Component预览组件

import React, { Component } from "react";

class Preview extends Component {

  constructor(props) {
    super(props);
    this.state = {
      firstName: this.props.firstName,
      lastName: this.props.lastName,
      title: this.props.title,
      address: this.props.address,
      phoneNum: this.props.phoneNum,
      email: this.props.email,
      description: this.props.description
    }
  }

  submitForm = () => {
    this.props.submitForm()
  }

  changeInput = () => {
    this.props.changeInput()
  }


  render() {
    const {firstName, lastName, title, address, phoneNum, email, description} = this.state;

    return (
      <div className="cvPreview">
        <div className="gridItem nameItem">
          <h1>{firstName} </h1>
          <h3>Data engineer</h3>
        </div>
       
...
    );
  }
}

I haven't included all of preview component because it is just elements.我没有包含所有预览组件,因为它只是元素。 I know I am not doing this correctly, I am getting a TypeError "Cannot read property 'target' of undefined" and I am pretty sure I shouldn't be defining these props this many times, but after everything I have tried, this was my last shot.我知道我没有正确执行此操作,我收到 TypeError “无法读取未定义的属性'目标'”,我很确定我不应该多次定义这些道具,但在我尝试了一切之后,这是我的最后一枪。 I am stuck, help.我卡住了,求助。

The issue is with your handleInputChange .问题在于您的handleInputChange setState should be a function call. setState应该是一个 function 调用。

handleInputChange = (event) => {
    this.setState({
      [event.target.name]: event.target.value,
    });
  };

This is how the setState API looks like React setState .这就是 setState API 看起来像React setState的样子。 Also i see that your state is dependent on props in Preview component.我还看到您的 state 依赖于Preview组件中的道具。

 this.state = {
       firstName: this.props.firstName,
       lastName: this.props.lastName,
       title: this.props.title,
       address: this.props.address,
       phoneNum: this.props.phoneNum,
       email: this.props.email,
       description: this.props.description
     }

This is not needed since you are passing the state to your children components as props.这不是必需的,因为您将 state 作为道具传递给您的子组件。 Your Children components will always re-render when there is a change in their props ( change in the state of the parent component).当您的子组件的道具发生变化时(父组件的 state 发生变化),您的子组件将始终重新渲染。

So in your preview component you can now remove the state and have this因此,在您的预览组件中,您现在可以删除 state 并拥有这个

const {firstName, lastName, title, address, phoneNum, email, description} = this.props;

This blog from @danAbramov explains the issues one might face when having their state dependent on props. @danAbramov 的这篇博客解释了当 state 依赖于道具时可能面临的问题。

state dependent on props state 依赖于道具

Issues问题

Main主要的

  1. handleInputChange the this.setState should be a function call. handleInputChange this.setState应该是一个 function 调用。

     handleInputChange = (event) => { const { name, value } = event.target; this.setState({ [name]: value, }); };

Form形式

  1. Storing passed props in local component state is anti-pattern in React, just reference the prop values directly.在本地组件 state 中存储传递的 props 是 React 中的反模式,只需直接引用 prop 值即可。 If you store them in state then you must also implement componentDidUpdate so you can update the local cache saved in state when the props update ( ie the state updated in parent ), this is just extra unnecessary work though.如果您将它们存储在 state 中,那么您还必须实现componentDidUpdate以便在道具更新时更新保存在 state 中的本地缓存(即 state 更新,尽管这只是在父级中更新的额外工作)。

  2. The changeInput handler doesn't consume an onChange event nor pass it on to this.props.changeInput , but similar to the previous point, just attach this.props.changeInput to the elements needing it. changeInput处理程序不使用onChange事件,也不将其传递给this.props.changeInput ,但与上一点类似,只需将this.props.changeInput附加到需要它的元素。

  3. The child component that needs the props.changeInput callback is the component rendering the inputs, ie in your case it seems is the Personal component.需要props.changeInput回调的子组件是呈现输入的组件,即在您的情况下,它似乎是Personal组件。

     class Form extends Component { render() { const { address, changeInput, description, email, firstName, lastName, phoneNum, submitForm, title, } = this.props; return ( <form className="cvForm" onSubmit={submitForm}> <Personal onChange={changeInput} // <-- pass change handler here firstName={firstName} lastName={lastName} title={title} address={address} phoneNum={phoneNum} email={email} description={description} />... </form> ); } }

Preview预习

  1. All same comments as for Form component.所有与Form组件相同的注释。 Don't locally store the passed props and use the this.props.changeInput callback directly.不要在本地存储传递的 props,直接使用this.props.changeInput回调。 Since this is a preview it likely doesn't need an onChange handler.由于这是一个预览,它可能不需要onChange处理程序。

     class Preview extends Component { render() { const { firstName, lastName, title, address, phoneNum, email, description } = this.props; return ( <div className="cvPreview"> <div className="gridItem nameItem"> <h1> {title} {firstName} {lastName} </h1> <h3>Data engineer</h3>... other fields </div> </div> ); } }

Demo演示

编辑 react-passing-state-down

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

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