【问题标题】:React update state with button only updates state once用按钮反应更新状态只更新一次状态
【发布时间】:2021-09-06 16:31:32
【问题描述】:

我在我的博客组件中添加了一个赞按钮,并在后端更新状态,但它只发生一次。一旦我按下“赞”按钮,“赞”计数的状态就会增加 1,但每次使用赞按钮进行的​​调用都会发出 PUT 请求,但不会增加计数。

App.js

import blogService from './services/blogs';
...

const App = () => {
  // All blogs display
  const [blogs, setBlogs] = useState([]);
  ....

  const updateBlog = async blogObject => {
    const updatedBlog = await blogService.update(blogObject.id, blogObject);
    setBlogs(
      blogs.map(blog => (blog.id !== updatedBlog.id ? blog : updatedBlog)),
    );
    console.log(updatedBlog);
    setMessage(`Liked "${updatedBlog.title}"`);
    setMessageClass('success');
    setTimeout(() => {
      setMessage(null);
      setMessageClass('none');
    }, 3000);
  };

...

return (
    <div>
      <Container>
        <p className={messageClass}>{message}</p>

        <p>{user.name} is logged in </p>
        {logOutForm()}
        <hr />
        <br />
        {blogForm()}
        <hr />
        <ul>
          {blogs.map(blog => (
            <Blog key={blog.id} blog={blog} updateBlog={updateBlog} />
          ))}
        </ul>
      </Container>
    </div>
  );

blogs.js (blogService)

import axios from 'axios';
const baseUrl = '/api/blogs';

....

const update = (id, newObject) => {
  const request = axios.put(`${baseUrl}/${id}`, newObject);
  return request.then(response => response.data);
};

Blog.js 组件

const Blog = ({ blog, updateBlog }) => {
  ...

  const [blogObject, setBlogObject] = useState(blog);

  const likeBlog = () => {
    let likes = blog.likes + 1;
    // Make a copy of the blog object and pass new likes count
    const editedBlog = { ...blog, likes };
    updateBlog(editedBlog);
    setBlogObject(editedBlog);
  };

  return (
    <div>
      <ListGroup variant className='m-3'>
        <div style={hideWhenVisible}>
          <ListGroup.Item>{blog.title} </ListGroup.Item>
          <Button
            onClick={toggleVisibility}
            style={buttonStyle}
            variant='primary'
          >
            View
          </Button>
        </div>
        <div style={showWhenVisible}>
          <ListGroup.Item>{blog.title} </ListGroup.Item>
          <ListGroup.Item>{blog.url}</ListGroup.Item>
          <ListGroup.Item>{blog.author}</ListGroup.Item>
          <ListGroup.Item>
            <Button
              variant='success'
              type='submit'
              style={{ marginLeft: '8px' }}
              onClick={likeBlog}
            >
              {blogObject.likes} likes
            </Button>
          </ListGroup.Item>
          <Button
            onClick={toggleVisibility}
            style={buttonStyle}
            variant='secondary'
          >
            Hide
          </Button>
        </div>
        <hr style={hrStyle} />
      </ListGroup>
    </div>
  );
};

Blogs.js(后端的控制器文件夹)

blogsRouter.put('/:id', async (request, response, next) => {
  const body = request.body;

  const blog = {
    author: body.author,
    title: body.title,
    url: body.url,
    likes: body.likes,
  };

  try {
    // Update command
    const editedBlog = await Blog.findByIdAndUpdate(request.params.id, blog, {
      new: true,
    });
    editedBlog.toJSON();
  } catch (exception) {
    next(exception);
  }
});

每次按下“喜欢”按钮时的控制台

---
Method: PUT
Path:   /api/blogs/61106affab47f571ae71e6c1
Body:   {
  likes: 9,
  title: 'My first blog',
  author: 'Mickey Daniels',
  url: 'http://localhost3003/api/blogs',
  id: '61106affab47f571ae71e6c1'
}
---
Method: PUT
Path:   /api/blogs/61106affab47f571ae71e6c1
Body:   {
  likes: 9,
  title: 'My first blog',
  author: 'Mickey Daniels',
  url: 'http://localhost3003/api/blogs',
  id: '61106affab47f571ae71e6c1'
}
---
Method: PUT
Path:   /api/blogs/61106affab47f571ae71e6c1
Body:   {
  likes: 9,
  title: 'My first blog',
  author: 'Mickey Daniels',
  url: 'http://localhost3003/api/blogs',
  id: '61106affab47f571ae71e6c1'
}
---

您在上面的控制台中看到,每次都发出 PUT 请求,但“喜欢”并没有增加。

【问题讨论】:

  • 问题分析得很好。

标签: reactjs state increment


【解决方案1】:

据我所知,您需要在您的Blog 组件中添加一个useEffect 挂钩,以便在更改后再次读取blog,例如:

useEffect(() => {
  setBlogObject(blog)
}, [blog]);

这将更新 likes 计数,因为它来自您对更新调用的 API 响应,但是,从我自己的角度来看,您可以直接依赖 Blog 组件上的 blog 属性,然后计算运行中的任何其他值,而无需使用状态挂钩停止。

============

更新 #1

另一种方法是将blog 引用更新为最新的引用(您存储在博客的组件状态中)。

  const likeBlog = () => {
    let likes = blogObject.likes + 1;
    // Make a copy of the blog object and pass new likes count
    const editedBlog = { ...blogObject, likes };
    updateBlog(editedBlog);
    setBlogObject(editedBlog);
  };

【讨论】:

  • 苏丹,我确实尝试了你提到的两种方法,它确实在视觉上更新了计数,但它实际上并没有在后端进行更改并更新数据库计数,除非我手动刷新页面。跨度>
  • @JackJack 我更新了我的答案,如果第二部分有效,请告诉我。
  • 成功了!谢谢!接受这个答案作为解决方案。
猜你喜欢
  • 1970-01-01
  • 2019-06-12
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 2021-06-02
  • 1970-01-01
  • 2018-03-28
相关资源
最近更新 更多