【问题标题】:Setting parent state after child rendered in React在 React 中渲染子后设置父状态
【发布时间】:2020-03-12 20:21:46
【问题描述】:

我正在处理图书馆项目。用户可以将书籍添加到图书馆。 因此,我创建了添加书籍的表单。该表单包含来自姓名、作者、出版商、页面、ISBN 和信息字段。我为作者和出版商创建了下拉组件,因此用户可以从该组件中进行选择:

import AuthorsService from './AuthorsService'

const authorsService = new AuthorsService();

class AuthorsDropDown extends Component {
    constructor(props) {
        super(props);
        this.state = {
            authors: [],
        };
    }
    componentDidMount() {
        var self = this;
        authorsService.getAuthors().then(function (result) {
            self.setState({ authors: result});
        });
    }

    render() {
        return (
            <div className="form-group col-sm-4">
            <label>Author:</label>
            <select className="form-control" onChange={(ev) => this.props.onChange(ev.target.value)}>
            {this.state.authors.map( a  => 
                    <option key={a.id} value={a.id}>{a.first_name + ' '+a.last_name }
                    </option>)
            }
            </select>
            </div>
        );
    }


}
export default AuthorsDropDown;

我已将父组件中的 author.id 和 publisher.id 字段的初始值分配为 null,但是,这些字段仅在下拉更改后(即 onChange 被触发后)才获得它们的值。我不知道如何在渲染时为它们设置值(即初始化状态)。这是父组件:

import React, { Component } from "react";
import BookService from "./BooksService";
import AuthorsDropDown from "./AuthorsDropDown";
import PublishersDropDown from "./PublishersDropDown";
const bookService = new BookService();


class BookCreateUpdate extends Component {


  constructor(props) {
    super(props);

    this.state = {
      author:{id:null},
      publisher:{id:null}
    }

    this.handleSubmit = this.handleSubmit.bind(this);
    this.onChangeAuthor = this.onChangeAuthor.bind(this);
    this.onChangePublisher = this.onChangePublisher.bind(this);
  }

    onChangeAuthor(new_author_id){
      this.setState({author:{id:new_author_id}});
    }

    onChangePublisher(new_publisher_id){
      this.setState({publisher:{id:new_publisher_id}});
    }

  handleCreate() {
    alert(this.state.author.id);
    bookService
      .createBook({
        name: this.refs.name.value,
        author: this.state.author,
        publisher: this.state.publisher,
        page: this.refs.pages.value,
        inventor_number: this.refs.inventor_number.value,
        description: this.refs.description.value
      })
      .then(result => {
        alert("The book is added!");
      })
      .catch(() => {
        alert("Error!!");
      });
  }

  handleUpdate(pk) {
    bookService
      .updateBook({
        pk: pk,
        name: this.refs.name.value,
        author: this.refs.author,
        publisher: this.refs.publisher,
        pages: this.refs.pages.value,
        description: this.refs.description.value
      })
      .then(result => {
        console.log(result);
        alert("Success");
      })
      .catch(() => {
        alert("Error.");
      });
  }

  handleSubmit(event) {
    const {
      match: { params }
    } = this.props;
    if (params && params.pk) {
      this.handleUpdate(params.pk);
    } else {
      this.handleCreate();
    }
    event.preventDefault();
  }

  render() {

    return (
      <form onSubmit={this.handleSubmit}>
          <div className="row">
            <div className="form-group  col-sm-8">
              <label>Name:</label>
              <input
                className="form-control"
                type="text"
                ref="name"/>
            </div>
          </div>
          <div className="row">
            <AuthorsDropDown onChange={this.onChangeAuthor}/>
            <PublishersDropDown onChange={this.onChangePublisher}/>
          </div>
          <div className="row">
            <div className="form-group col-sm-4">
              <label>Pages:</label>
              <input
                className="form-control"
                type="number"
                ref="pages"/>
            </div>
            <div className="form-group  col-sm-4">
              <label>ISBN:</label>
              <input
                className="form-control"
                type="text"
                ref="inventor_number"/>
             </div>
             </div>
            <div className="row">
              <div className="form-group col-sm-4">
                <label>Info:</label>
                <textarea
                  className="form-control"
                  ref="description"/>
              </div>
            </div>
            <input className="btn btn-primary" type="submit" value="ok"/>
      </form>
    );
  }

}
export default BookCreateUpdate;

【问题讨论】:

  • 抱歉,您的问题有点混乱。您的意思是在父组件中设置一个选定的默认 author_id 和 publisher_id 吗?
  • 是的,我的意思是这个

标签: javascript reactjs dropdown


【解决方案1】:

我认为您应该考虑另一种解决此问题的方法。如果我了解您的要求,此组件将创建和更新书籍。在这种情况下,&lt;BookCreateUpdate/&gt; 组件应该接收一个属性,即目标书。对于创建,它应该是一个空对象。对于更新,它应该是要更新的对象。

我认为上述问题与编辑时有关。我想这些书都保存在某个地方。如果一本书是在编辑模式下传递的,那么初始值应该从父组件 (&lt;BookCreateUpdate/&gt;) 向下传递给子组件(输入、AuthorsDropDown、PublishersDropDown)。

class BookCreateUpdate extends Component {

  constructor(props) {
    super(props);
    this.state(this.props.book)
  }

 onInputChange = propName => (e) => {
   this.setState({[propName]: e.target.value })
 }

  ...

   handleCreate() {
    const bookDraft = this.state;
    bookService
      .createBook(bookDraft)
      .then(result => {
        alert("The book is added!");
      })
      .catch(() => {
        alert("Error!!");
      });
  }
  ...
  render(){
     const bookDraft = this.state;
     return (
     ...
     <div className="row">
            <div className="form-group  col-sm-8">
              <label>Name:</label>
              <input
                className="form-control"
                type="text"
                value = {bookDraft.name}
                onChange={this.onInputChange('name')}
               />
            </div>
     </div>
     <AuthorsDropDown onChange={this.onChangeAuthor} authorId = {bookDraft.authorId}/>
     <PublishersDropDown onChange={this.onChangePublisher} publisherId = {bookDraft.publisherId}/>
     ....
)
  }
}
BookCreateUpdate.propsTypes = {
  book: PropTypes.object
}
BookCreateUpdate.defaultProp = {
  book: {authorId: null, publisherId: null}
}

在这种情况下最好不要使用 refs。将值传递给 input 并为 onChange 事件传递回调会更简洁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-10
    • 1970-01-01
    • 2021-06-11
    • 2019-09-16
    • 1970-01-01
    • 2017-10-22
    • 2017-02-03
    • 1970-01-01
    相关资源
    最近更新 更多