猿问

使用 React.JS 预填充表单

所以,我对 React 很陌生,无法解决这个问题。我正在尝试使用父组件从数据库中获取的信息预先填充表单。子组件应该将数据显示为默认值,然后在用户编辑表单时更改状态。这就是我将数据作为道具传递的方式(编辑 2):



componentDidMount() {

    const ticketID = this.props.match.params.ticketID;

    axios.get(`http://127.0.0.1:8000/api/tickets/${ticketID}`).then(res => {

      this.setState({ ticket: res.data }, () => console.log(this.state.ticket));

    });

  }


{this.state && this.state.ticket ? (

  <TicketForm

    requestType="put"

    ticketID={this.props.match.params.ticketID}

    btnText="Update"

    ticket={this.state.ticket}

    />

 ) : (

  <div />

    )}

这工作正常。我能够获取数据并将其记录在 console.log 中,但我无法将其设置为默认状态。表单保持空白,当我尝试在其上键入内容时会抛出警告:“组件正在更改要控制的文本类型的不受控制的输入。输入元素不应从不受控制切换到受控制(反之亦然)”。<--- 已解决(编辑 2)


我遵循了本教程https://www.youtube.com/watch?v=IK9k9hSuYeA&t=373s。


子组件如下:


class TicketForm extends React.Component {

   constructor(props) {

    super(props);

    this.state = {

      name: props.ticket.name || "",

      description: props.ticket.description || ""


    };


    handleChange = e => {

    this.setState({

      [e.target.name]: e.target.value

      });

    }; 


    (...)



   render() {

    return (

      <div className="form-container">

        <div className="card mb-3">

          <div className="card-header">

            <h2>{this.state.btnText} Ticket</h2>

          </div>

          <div className="card-body">

            <form

              onSubmit={e =>

                this.onSubmit(e, this.props.requestType, this.props.ticketID)

              }

)}

我花了几个小时试图解决这个问题并在这里阅读了一堆帖子,但仍然无法解决这个问题。任何帮助将非常感激。


编辑 1:我终于弄明白了为什么在构造函数上未定义 props。当我将票证作为道具传递时,票证仍在从数据库中获取,因此构造函数接收到的值仍然未定义。


编辑 2:尝试在父子节点上使用三元运算符,以确保仅在完全设置状态后才传递道具。


慕容3067478
浏览 201回答 3
3回答

四季花海

仅当name或的初始状态description未定义时才会发生此错误,您没有在代码中检查。尝试将您的构造函数更改为:&nbsp; &nbsp;constructor(props) {&nbsp; &nbsp; super();&nbsp; &nbsp; this.state = {&nbsp; &nbsp; &nbsp; name: props.ticket.name || '',&nbsp; &nbsp; &nbsp; description: props.ticket.description || '',&nbsp; &nbsp; };这样,如果您有任何一个undefined值,您仍然可以将空字符串设置为后备值。

鸿蒙传说

你应该super()用 props 作为参数调用:super(props)constructor(props) {&nbsp; super(props);&nbsp; // <-- instead of super()&nbsp; this.state = {&nbsp; &nbsp; name: props.ticket.name,&nbsp; &nbsp; description: props.ticket.description&nbsp; };&nbsp; ...}我不确定这有什么不同,似乎this.state.ticket之前通过的设置没有正确。你能试试看console.log(this.state.ticket)它是否确实是表单的对象{name: ..., description: ...}吗?

撒科打诨

这应该有效:在深入研究之前,您应该了解 state 和 props 的基础知识。当您在构造函数中初始化一个状态时,它只会被初始化一次。React 没有办法根据 props 更新组件状态。因此,为了实现这一点,他们提供了一个getDerivedStateFromProps顾名思义的钩子来从道具中导出状态。希望它可以帮助您清除您的疑问。另一方面,我鼓励您从 React Hooks 而不是类组件开始,因为使用useEffect功能组件可以轻松处理这些错误。我希望我能给你一个更好的概述。如果您仍然发现任何困难,请告诉我。class TicketForm extends React.Component {&nbsp; &nbsp;constructor(props) {&nbsp; &nbsp; super(props);&nbsp; &nbsp; this.state = {&nbsp; &nbsp; &nbsp; name: "",&nbsp; &nbsp; &nbsp; description: ""&nbsp; &nbsp; };&nbsp; &nbsp;static getDerivedStateFromProps(props, state) {&nbsp;&nbsp; &nbsp; // Stringify as to check ticket is an object. In case it is a string&nbsp; &nbsp; // or integer you can directly, check the equality&nbsp; &nbsp; if (JSON.stringify(props.ticket) !== JSON.stringify(state)) {&nbsp; &nbsp; &nbsp;return {&nbsp; &nbsp; &nbsp; name: props.ticket.name,&nbsp; &nbsp; &nbsp; description: props.ticket.description&nbsp; &nbsp; &nbsp;}&nbsp; &nbsp; }&nbsp; &nbsp; return null;&nbsp; &nbsp;}&nbsp; &nbsp; handleChange = e => {&nbsp; &nbsp; this.setState({&nbsp; &nbsp; &nbsp; [e.target.name]: e.target.value&nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; };&nbsp;&nbsp; &nbsp; (...)&nbsp; &nbsp;render() {&nbsp; &nbsp; return (&nbsp; &nbsp; &nbsp; <div className="form-container">&nbsp; &nbsp; &nbsp; &nbsp; <div className="card mb-3">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div className="card-header">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <h2>{this.state.btnText} Ticket</h2>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div className="card-body">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <form&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onSubmit={e =>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.onSubmit(e, this.props.requestType, this.props.ticketID)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; >&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div className="form-group">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <label htmlFor="name">Name</label>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <input&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type="text"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name="name"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; className="form-control form-control-lg"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; placeholder="Ticket name"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value={this.state.name}&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onChange={e => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.handleChange(e);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div className="form-group">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <label htmlFor="description">Description</label>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <textarea&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name="description"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; className="form-control form-control-lg"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rows="3"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; placeholder="Ticket Description"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value={this.state.description}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onChange={e => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.handleChange(e);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ></textarea>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(...))}
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答