简体   繁体   English

state 挂钩未在更改时更新 state

[英]state hooks is not updating state on change

I am building a simple blog app and I am trying to update title of the blog But it is not updating, it is just showing the current state.我正在构建一个简单的博客应用程序,我正在尝试更新博客的title但它没有更新,它只是显示当前的 state。

I have tried many times by changing the method of setting state but it is still showing that error.我通过更改设置 state 的方法尝试了很多次,但它仍然显示该错误。

App.js应用程序.js

function BlogDetail() {
    const [blogName, setBlogName] = useState("");


    axios.get("/api/blog_detail/70/").then(res => {

       setBlogName(res.data[0].blog_name)
    })

  const handleChange = (e) => {
    console.log(e.target.value)
    setBlogName({
      ...blogName,
      [e.target.name]: e.target.value
    })
  }

  const saveBlog = (e) => {
   // sending to API
   console.log(blogName)
  }

   return (
       <div>
       <form>

       {blogName}


       <input type="text" name="blogName" value={blogName} onChange={e => handleChange} />

       <button type="submit" onClick={e => saveBlog(e)}>Save</button>


       <form>
       </div>


   )
}

And When I update on change instead of updating on submit当我更新更改而不是更新提交时

onChange=(e => setBlogName(e.target.value))

Then it is showing然后它显示

A component is changing a controlled input to be uncontrolled.组件正在将受控输入更改为不受控。 This is likely caused by the value changing from a defined to undefined这可能是由于值从已定义更改为未定义引起的

I have tried many times but it is still not working.我已经尝试了很多次,但它仍然无法正常工作。

input requires a string as a value, but you are trying to pass an object: input需要一个字符串作为值,但您正在尝试传递 object:

setBlogName({
  ...blogName,
  [e.target.name]: e.target.value
})

instead pass a string:而是传递一个字符串:

setBlogName(e.target.value)

Also, you need to execute handleChange function and pass the event param.此外,您需要执行handleChange function 并传递event参数。

onChange={e => handleChange(e)}

Edit:编辑:

Looked at it second time and it should be like this:第二次看了,应该是这样的:


function BlogDetail() {
    const [blogName, setBlogName] = useState("");

    // without this you override state every time you press a key
    useEffect(() => {
      axios.get("/api/blog_detail/70/").then(res => {

         setBlogName(res.data[0].blog_name)
      })
    }, [])

  const handleChange = (e) => {
    // just use value here
    setBlogName(e.target.value)
  }

  const saveBlog = (e) => {
   // sending to API
   console.log(blogName)
  }

   return (
       <div>
       <form>

       {blogName}

       { /* remember to run the function */ }
       <input type="text" name="blogName" value={blogName} onChange={e => handleChange()} />

       <button type="submit" onClick={e => saveBlog(e)}>Save</button>


       <form>
       </div>


   )
}

Besides the problem that within handleChange you need to pass an an string value to setBlogName you also need to wrap your axios fetch call in a useEffect .除了在handleChange您需要将字符串值传递给setBlogName的问题之外,您还需要将 axios fetch 调用包装在useEffect中。

The problem is that everytime you trigger a rerender while calling setBlogName you are calling your API point again and set the value back to the fetched value.问题是每次您在调用setBlogName时触发重新渲染时,您都会再次调用 API 点并将值设置回获取的值。

You should prevent that by doing the following ->您应该通过执行以下操作来防止这种情况 ->

useEffect(() => {
  axios.get("/api/blog_detail/70/").then(res => {
     setBlogName(res.data[0].blog_name)
  }), [])

Don't forget to install { useEffect } from 'react' .不要忘记install { useEffect } from 'react'

And well of course update handleChange ->当然还有更新handleChange ->

const handleChange = (e) => {
    const newBlogPostName = e.target.value
    console.log(newBlogPostName)
    setBlogName(newBlogPostName)
  }

you have not any action in this method.您在此方法中没有任何操作。 where is the update state?更新 state 在哪里?

const saveBlog = (e) => {
   // sending to API
   console.log(blogName)


  }

and in this method you change the string to an object在这种方法中,您将字符串更改为 object

const handleChange = (e) => {
    console.log(e.target.value)
    setBlogName({
      ...blogName,
      [e.target.name]: e.target.value
    })
  }

so the problem is that your function updates your state to an object and then you want to display that object(not a string property of that object) in the DOM .所以问题是您的 function 将您的 state 更新为 object 然后您想在DOM中显示该对象(不是该对象的字符串属性)。 its wrong because you cant display objects in the DOM in react.它是错误的,因为您无法在DOM中显示对象以做出反应。 in this case, you even get an error because you cant use spread operator on strings .在这种情况下,您甚至会收到一个错误,因为您不能在strings上使用spread operator you cant do something like this: ...("test")你不能做这样的事情: ...("test")

  const handleChange = (e) => {
    console.log(e.target.value)
    //the state value will be an object. its wrong. you even get an error 
    because of using spread operator on a string
    setBlogName({
      ...blogName //this is a string at the init time,
      [e.target.name]: e.target.value
    })
  }

so whats the solution?那么解决方案是什么? you should update your state to a string or use a string property of the object.您应该将 state 更新为字符串或使用 object 的字符串属性。 something like this:像这样的东西:

      const handleChange = (e) => {
        console.log(e.target.value)

        setBlogName("string")
      }

      return (<>{blogName}</>)

thats it.而已。

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

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