【问题标题】:onClick function requires two clicks to update stateonClick 功能需要两次点击才能更新状态
【发布时间】:2021-02-26 15:19:18
【问题描述】:

我正在尝试创建一个具有收藏功能的应用。 该功能实际上有效,但仅在第二次点击之后。

编辑以获取更多信息:在第一次点击时,应用程序尝试将信息发送到我的数据库,但它不完整。它只是发送我的初始值。在第二次单击时,它最终会附加额外的必需值并保存到数据库中。

我对钩子很陌生,所以请随时评论我的代码可以使用的任何改进。 这是我处理所有事情的 React 组件。

import React, { useState, useEffect } from 'react';
import { Button } from 'react-bootstrap';

const ItemInfo = (props) => {

  const [item, setItem] = useState([]);
  const [ favorite, setFavorite ] = useState({favoritable_type: 'Item', favoritor_type: 'User' })

  useEffect(() => {
    fetch(`/items/${props.match.params.id}`)
    .then((response)=>{
      if(response.status === 200){
          return(response.json())
        }
      })
      .then((item) => {
        setItem(item);
      })
  }, []);

  const createFavorite = (data) => {
    fetch(`/favorites`, {
      body: JSON.stringify(data),
      headers: {
        'Content-Type': 'application/json',
        'X-CSRF-TOKEN': props.token
      },
      method: 'POST'
    })
    .then((resp) => {
      if (resp.ok) {
        setFavorite({})
        alert('This items has been favorited!')
      }
    })
    .catch((err) => {
      if (err) {
        console.log(err)
      }
    })
  }

  const handleFavorite = () => {
    const value = { favoritor_id: props.current_user.id, favoritable_id: item.id }
    setFavorite(favorite => ({...favorite, value}));
    createFavorite(favorite)
  }

老实说,我不确定这是做什么的。 我遇到了一个类似的答案,它似乎在控制台中解决了问题,但在实际的 POST 尝试中没有解决。

  useEffect(()=> {
    console.log(favorite)
  },[favorite])

这一切似乎都很好。

  if (item === null) {
    return <div>Loading...</div>
  } 

  return (
    <React.Fragment>
    <Button onClick={ handleFavorite } >Favorite</Button>
      <h1>{item.title}</h1>
      <p>{item.body}</p>
      <p>{item.user_id}</p>
    </React.Fragment>
  );
};

export default ItemInfo;

我尝试将一些功能分成不同的组件,使用类组件重新创建它,但无法弄清楚。

提前致谢!

【问题讨论】:

    标签: javascript reactjs react-hooks use-effect use-state


    【解决方案1】:

    由于挂钩值是常量,它们不会随着 setHookName 立即改变,它们会在下一次渲染时改变。您可以通过将代码注入到 setHookName 函数中来解决这个问题,如下所示:

    const handleFavorite = () => {
      setFavorite(oldFavorite => {
        const value = { favoritor_id: props.current_user.id, favoritable_id: item.id };
        const newFavorite = {...oldFavorite, ...value};
        createFavorite(newFavorite);
        return newFavorite;
      });
    }
    

    【讨论】:

    • 感谢您的快速回答!我尝试了您的建议,但结果相同。我想我可能没有解释清楚。我遇到的问题是我的 onClick 触发了我的 createFavorite(POST) 函数,这是应该的,但是发送到后端的状态只是我的初始值。直到第二次单击才会添加其他值,然后将其发送并保存在数据库中。
    • 这是一个奇怪的结果,因为newFavorite 本身并不是一个钩子,而是由oldFavorite 结合value 的值定义的,而newFavorite 直接输入到@ 987654326@,最后oldFavorite 变成newFavorite。我已经稍微修改了这个答案,所以试试吧。让我知道结果,并确保复制并替换整个旧的 handleFavorite = () =&gt; {...} 部分
    • @Plankartes7 常量没有按您希望的方式工作的原因是,虽然您确实传播了oldFavorite,但您也没有传播value 变量。我注意到了这一点,但我在想你没有传播它,因为我虽然你希望 value 成为收藏夹的属性,而不是 value 内部的值成为收藏夹的属性。请查看我的新编辑,请单击赞成/反对按钮旁边的复选标记,将其标记为正确的解决方案。
    • 这有点难以解释,因为您实际上并不需要 favorite 成为钩子 (useState)。尝试使用const favoriteTemplate = {favoritable_type: 'Item', favoritor_type: 'User' }; const value = { favoritor_id: props.current_user.id, favoritable_id: item.id }; createFavorite({...oldFavorite, ...value});(在handleFavorite()函数内部,你必须改变并且你必须删除在createFavorite()函数中设置状态)
    • 但除此之外,当您使用setHookName() 函数时,它内部的函数的返回值是钩子的下一个值。对于单线箭头函数,如() =&gt; 5;,5 是隐含的返回。使用() =&gt; {...} 类型函数,您必须明确告诉它返回某个值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-05
    • 2013-07-01
    相关资源
    最近更新 更多