为了账号安全,请及时绑定邮箱和手机立即绑定

使用 React.JS 预填充表单

使用 React.JS 预填充表单

慕容3067478 2021-12-12 15:25:17
所以,我对 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:尝试在父子节点上使用三元运算符,以确保仅在完全设置状态后才传递道具。
查看完整描述

3 回答

?
四季花海

TA贡献1811条经验 获得超5个赞

仅当name或的初始状态description未定义时才会发生此错误,您没有在代码中检查。


尝试将您的构造函数更改为:


   constructor(props) {

    super();

    this.state = {

      name: props.ticket.name || '',

      description: props.ticket.description || '',


    };

这样,如果您有任何一个undefined值,您仍然可以将空字符串设置为后备值。


查看完整回答
反对 回复 2021-12-12
?
鸿蒙传说

TA贡献1865条经验 获得超7个赞

你应该super()用 props 作为参数调用:super(props)


constructor(props) {

  super(props);  // <-- instead of super()

  this.state = {

    name: props.ticket.name,

    description: props.ticket.description

  };


  ...

}

我不确定这有什么不同,似乎this.state.ticket之前通过的设置没有正确。你能试试看console.log(this.state.ticket)它是否确实是表单的对象{name: ..., description: ...}吗?


查看完整回答
反对 回复 2021-12-12
?
撒科打诨

TA贡献1934条经验 获得超2个赞

这应该有效:在深入研究之前,您应该了解 state 和 props 的基础知识。当您在构造函数中初始化一个状态时,它只会被初始化一次。React 没有办法根据 props 更新组件状态。因此,为了实现这一点,他们提供了一个getDerivedStateFromProps顾名思义的钩子来从道具中导出状态。希望它可以帮助您清除您的疑问。


另一方面,我鼓励您从 React Hooks 而不是类组件开始,因为使用useEffect功能组件可以轻松处理这些错误。我希望我能给你一个更好的概述。如果您仍然发现任何困难,请告诉我。


class TicketForm extends React.Component {

   constructor(props) {

    super(props);

    this.state = {

      name: "",

      description: ""


    };


   static getDerivedStateFromProps(props, state) { 

    // Stringify as to check ticket is an object. In case it is a string

    // or integer you can directly, check the equality

    if (JSON.stringify(props.ticket) !== JSON.stringify(state)) {

     return {

      name: props.ticket.name,

      description: props.ticket.description

     }

    }

    return null;

   }


    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)

              }

            >

              <div className="form-group">

                <label htmlFor="name">Name</label>

                <input

                  type="text"

                  name="name"

                  className="form-control form-control-lg"

                  placeholder="Ticket name"

                  value={this.state.name} 

                  onChange={e => {

                    this.handleChange(e);

                  }}

                />

              </div>

              <div className="form-group">

                <label htmlFor="description">Description</label>

                <textarea

                  name="description"

                  className="form-control form-control-lg"

                  rows="3"

                  placeholder="Ticket Description"

                  value={this.state.description}

                  onChange={e => {

                    this.handleChange(e);

                  }}

                ></textarea>

              </div>

             (...)


)}


查看完整回答
反对 回复 2021-12-12
  • 3 回答
  • 0 关注
  • 200 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信