从 Axios 响应中填充输入字段 ReactJS

3

我有一些简单的字段。我希望根据从axios响应中获取的数据填充输入框。请参见下面的图片。

enter image description here

我正在使用hooks将数据保存到状态中。 我的问题是,如何在点击“获取详细信息”按钮时填充输入框(来自API的响应)。

请参见以下代码:

const [data, setData] = useState([])
const [advisoryDetails, setadvisoryDetails] = useState({
    ADVISORYID: '',
    ADVISORYDESC: '',
    CREATEDBY:'',
    MODIFIEDBY:'',
    STATUS1: ''        
})
const [advisoryDetails1, setadvisoryDetails1] = useState([])
const [advisoryID, setadvisoryID] = useState('')

const getAdvisoryTest = async () => {
    await axios.post('/API',advisoryID)
    .then(response => {
        console.log(response.data)
        setData(response.data)
        console.log('data',data)
        setadvisoryDetails1(response.data)
        console.log('advisoryDetails1',advisoryDetails1)
        alert('success')
    })

advisoryDetails1.map(adv => {
        advisoryDetails.ADVISORYID = adv.ADVISORYID;
        advisoryDetails.ADVISORYDESC = adv.ADVISORYDESC;
        advisoryDetails.CREATEDBY = adv.CREATEDBY;
        advisoryDetails.MODIFIEDBY = adv.MODIFIEDBY;
        if(adv.CREATEDBY && adv.MODIFIEDBY != '')
        {
            advisoryDetails.STATUS1 = 'Modified'
        }
        else{ advisoryDetails.STATUS1 = 'New'}

        console.log('populate',advisoryDetails)
    })
}
const txtAdvIdOnChange = e =>{
    setadvisoryID(prevState =>({
        ...prevState,
        'ADVISORYID':e.target.value
    }));
    console.log('onChange ID:',advisoryID)
}
return(
    <div>
        <label>AdvisoryID: </label>
        <input type='text' placeholder='Advisory ID' className='txtAdvisoryID' onChange={txtAdvIdOnChange} />
<button onClick={()=>getAdvisoryTest()}>Get Details</button>
        <br /><br />
<label>Advisory Desc: </label>
        <input type='text' placeholder='textbox1' className='txtAdvisoryDesc' value={advisoryDetails&&advisoryDetails.ADVISORYDESC} disabled/>
        <br/>
        <label>New / Modified: </label>
        <input type='text' placeholder='textbox2' className='txtStatus' value={advisoryDetails&&advisoryDetails.STATUS1} disabled/>
</div>)

在那些代码中,输入框没有被填充,即使在console.log中也是如此。 希望我能帮到你,谢谢。

为什么你要使用 advisoryDetails.STATUS1 = 'Modified'?使用 setadvisoryDetails 来更新状态,像这样:setadvisoryDetails(prevState => ({...prevState, STATUS1: "Modified"})) - Haseeb Ahmad
你知道由于你正在遍历数组 advisoryDetails1,它只会覆盖数据到 advisoryDetails,因此你将看到最后一次迭代的值。 - Haseeb Ahmad
@HaseebA 哦,是的,哈哈,我的错。但是我仍然有问题,在单击“获取详细信息”按钮时填充输入框。 - Rymrk
1
如果你将 response.data 设置为 advisoryDetails1,那么为什么不使用响应的数据来更新它,因为此时可能 advisoryDetails1 尚未更新。const respData = response.data; if (respData.length > 0) { const adv = respData[respData.length-1]; setadvisoryDetails((prevState) => ({ ...prevState, ...adv, STATUS1: adv.CREATEDBY && adv.MODIFIEDBY != '' ? '已修改' : '新建' })) } - Haseeb Ahmad
嗨@HaseebA,你能发表你的答案吗?这样我就可以标记它为正确答案了。谢谢。 - Rymrk
3个回答

1
当您点击“获取详细信息”按钮时,您的状态未更新,这就是问题所在(只有在状态更新时值才会更改,否则它不会被更新)。
//before don't do like this 
advisoryDetails1.map(adv => {
        advisoryDetails.ADVISORYID = adv.ADVISORYID;
        advisoryDetails.ADVISORYDESC = adv.ADVISORYDESC;
        advisoryDetails.CREATEDBY = adv.CREATEDBY;
        advisoryDetails.MODIFIEDBY = adv.MODIFIEDBY;
        if(adv.CREATEDBY && adv.MODIFIEDBY != '')
        {
            advisoryDetails.STATUS1 = 'Modified'
        }
        else{ advisoryDetails.STATUS1 = 'New'}

        console.log('populate',advisoryDetails)
    })





//after(only last element of advisoryDetails1 array was updated in the state)
 advisoryDetails1.forEach(adv => {
    let STATUS1 ='New'
    if(adv.CREATEDBY && adv.MODIFIEDBY != '')
    {
        STATUS1  = 'Modified'
    }
   
     setadvisoryDetails({ADVISORYID : adv.ADVISORYID,
        ADVISORYDESC:adv.ADVISORYDESC,
        CREATEDBY:adv.CREATEDBY,
        MODIFIEDBY:adv.MODIFIEDBY,
       STATUS1:STATUS1 
     })
   })

如果您想查看advisoryDetails1数组中的最后一个元素,请按照以下方式操作。
 let adv=advisoryDetails1[advisoryDetails1.length -1];
    let STATUS1 ='New'
    if(adv.CREATEDBY && adv.MODIFIEDBY != '')
    {
        STATUS1  = 'Modified'
    }
   
     setadvisoryDetails({ADVISORYID : adv.ADVISORYID,
        ADVISORYDESC:adv.ADVISORYDESC,
        CREATEDBY:adv.CREATEDBY,
        MODIFIEDBY:adv.MODIFIEDBY,
        STATUS1:STATUS1 
     })
 


 //it update your advisoryDetails state when advisoryDetails1 changed
  useEffect(()=>{
    advisoryDetails1.forEach(adv => {
    let STATUS1 ='New'
    if(adv.CREATEDBY && adv.MODIFIEDBY != '')
    {
        STATUS1  = 'Modified'
    }
   
     setadvisoryDetails({ADVISORYID : adv.ADVISORYID,
        ADVISORYDESC:adv.ADVISORYDESC,
        CREATEDBY:adv.CREATEDBY,
        MODIFIEDBY:adv.MODIFIEDBY,
       STATUS1:STATUS1 
     })
   })
  },[advisoryDetails1]);
//check whether advisoryDetails is changed or not 
      useEffect(()=>{
        console.log('populate',advisoryDetails)
      },[advisoryDetails])

一切都很好,但是它不会像这样做,只有数组的最后一个元素被更新,因此您需要根据您的要求进行一些更改。


嗨@baskaran-ajiharan,使用您的第二组代码(在//注释之后)后,advisoryDetails在第一次单击时尚未填充数据(我通过console.log进行了检查)。我想在点击按钮后立即填充advisoryDetails,以便我可以立即使用它并填充输入框。谢谢 - Rymrk
我确保axios响应仅返回一组数据。 - Rymrk
我刚刚更新了我的答案,你能再检查一下吗?你不能直接使用console.log语句进行检查,因为它是异步的。你只能使用render方法或useEffect hook进行检查。如果你的数据只有一个集合,则在后端返回时应该作为对象而不是数组。 - Baskaran Ajiharan

1

我认为你可以像下面这样重构你的代码。我已经将 setadvisoryDetails 移到了 axios.then() 内部,因为你正在使用相同的数据,如果你只想要最后一次迭代的值,就不需要通过循环来实现。在输入中,你不必检查 advisoryDetails 是否存在或是否具有非空值,因为你已经在 const [advisoryDetails, setadvisoryDetails] = useState({...}) 中对其进行了初始化。

const App = (props) => {
  const [data, setData] = useState([])
  const [advisoryDetails, setadvisoryDetails] = useState({
    ADVISORYID: '',
    ADVISORYDESC: '',
    CREATEDBY: '',
    MODIFIEDBY: '',
    STATUS1: ''
  })
  const [advisoryDetails1, setadvisoryDetails1] = useState([])
  const [advisoryID, setadvisoryID] = useState('')

  const getAdvisoryTest = () => {
    axios.post('/API', advisoryID)
      .then(response => {
        const respData = response.data;
        setData(respData)
        setadvisoryDetails1(respData)

        console.log({
          respData, data, advisoryDetails1
        });

        alert('success');

        if (respData.length > 0) {
          const adv = respData[respData.length - 1];
          setadvisoryDetails((prevState) => ({
            ...prevState,
            ...adv,
            STATUS1: adv.CREATEDBY && adv.MODIFIEDBY != '' ? 'Modified' : 'New'
          }))
        }

      })
  }

  const txtAdvIdOnChange = e => {
    setadvisoryID(prevState => ({
      ...prevState,
      'ADVISORYID': e.target.value
    }));
    console.log('onChange ID:', advisoryID)
  }

  return (
    <div>
      <label>AdvisoryID: </label>
      <input type='text' placeholder='Advisory ID' className='txtAdvisoryID' onChange={txtAdvIdOnChange} />
      {/* If you're just passing a function without any param or event params, then just pass the function name like a variable */}
      <button onClick={getAdvisoryTest}>Get Details</button>
      <br /><br />
      <label>Advisory Desc: </label>
      <input type='text' placeholder='textbox1' className='txtAdvisoryDesc' value={advisoryDetails.ADVISORYDESC} disabled />
      <br />
      <label>New / Modified: </label>
      <input type='text' placeholder='textbox2' className='txtStatus' value={advisoryDetails.STATUS1} disabled />
    </div>
  );
}

0
在您的输入值属性中,尝试在 && 两侧添加一个空格。
<input type='text' placeholder='textbox2' className='txtStatus' value={advisoryDetails.STATUS1 && advisoryDetails.STATUS1} disabled/>

仍然遇到相同的问题。 - Rymrk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接