首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >重复键在反应,不能解决问题。遇到两个拥有相同密钥的孩子

重复键在反应,不能解决问题。遇到两个拥有相同密钥的孩子
EN

Stack Overflow用户
提问于 2019-12-27 14:32:30
回答 2查看 4.3K关注 0票数 0

错误:

警告:遇到两个具有相同密钥的子级,5e0611d77833da1668feade1。键应该是唯一的,这样组件就可以在更新中维护其标识。非唯一的键可能会导致子键被复制和/或省略--这种行为是不支持的,并且可能在将来的版本中更改。

在这张图片上,我创建了2个博客。删除按钮正常工作。我是通过axios发送到HTTP请求的,使用猫鼬和MongoDB作为我的数据库。

但是当我开始点击“喜欢”按钮时,看看会发生什么。,它删除了我的另一篇博文,并以相同的名字和id复制了一篇。这里的问题是,我有不同的ID,但不知怎的,当我按下“喜欢”按钮时,它会给我另一个ID。

我将为您提供后端的请求和incrementLikes的前端代码,我真的不知道发生了什么。

控制器/blogs.js(后端)

代码语言:javascript
运行
复制
blogsRouter.put('/:id', async (request, response, next) => {

  const body = request.body
  const blogs = {
    title:body.title,
    author: body.author,
    url:body.url,
    likes: body.likes
  }

  try {
    const updatedBlog = await Blog.findOneAndUpdate(request.params.id, blogs, {
      new: true
    })
    response.json(updatedBlog.toJSON())
  } catch (exception) {
    next(exception)
  }
})

App.js

代码语言:javascript
运行
复制
import React, { useState, useEffect } from 'react';
import './App.css';
import Blog from './components/Blog';
import LoginForm from './components/LoginForm'
import BlogForm from './components/BlogForm'
import Notification from './components/Notification'

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


const App = () => {

  const [blogs, setBlogs] = useState([])
  const [user, setUser] = useState(null)
  const [username, setUsername] = useState('')
  const [password, setPassword] = useState('')
  const [errorMessage, setErrorMessage] = useState(null)

  // states for blog creation
  const [title, setTitle] = useState('')
  const [author, setAuthor] = useState('')
  const [url, setUrl] = useState('')

  useEffect(() => {
    console.log('effect')
    blogService
    .getAll()
    .then(response => {
      console.log('promise fulfiled')
      setBlogs(response.data)

    })
    .catch(error => {
      console.log('response', error.response)
      console.log('error')
    })
  }, [])

  useEffect(() => {
    const loggedUserJSON = window.localStorage.getItem('loggedBlogUser')
    if (loggedUserJSON) {
      const user = JSON.parse(loggedUserJSON)
      setUser(user)
      blogService.setToken(user.token)
    }
}, [])

  //put request
  ***const incrementLike = id => {
    const blog = blogs.find(b => b.id === id)
    console.log('blog id', blog)
    const voteLike = {...blog, likes: blog.likes + 1}

    blogService
    .update(id, voteLike)
    .then(returnedBlog => {
      setBlogs(blogs.map(blog => blog.id !== id ? blog : returnedBlog))
    })
    .catch(error => {
      setErrorMessage(
        `Blog was already removed from server`
      )
      setTimeout(() => {
        setErrorMessage(null)
      }, 5000)
      })
  }***

  //login
  const handleLogin = async (e) => {
    e.preventDefault()

    try {
      const user = await loginService.login({username, password})

      window.localStorage.setItem('loggedBlogUser', JSON.stringify(user))

      setUser(user)
      setUsername('')
      setPassword('')
      console.log('success')
    } catch (exception) {
        setErrorMessage('wrong credentials')
        setTimeout(() => {
          setErrorMessage(null)
        }, 5000)
        console.log('baaad')
    }
  }

  const deleteBlogId = (id) => {
    console.log('deleted blog')
    blogService
    .del(id)
    .then(response => {
      setBlogs(blogs.filter(blog => blog.id !== id))
    })
    .catch(error => {
      console.log(error.response);
    })
  }

  const handleCreateBlog = async (e) => {
    e.preventDefault()
    const newBlogs = {
      title: title,
      author: author,
      url: url,
      date: new Date()
    }

    blogService
    .create(newBlogs)
    .then(returnedBlog => {
      setBlogs(blogs.concat(returnedBlog))
      setTitle('')
      setAuthor('')
      setUrl('')
      setErrorMessage(`${author} created new blog with name ${title}`)
      setTimeout(() => {
        setErrorMessage(null)
      }, 5000)
    })
  }


  const loginForm = () => {

    return (
      <div>
        <Notification message={errorMessage}/>
        <div>
          <LoginForm 
            username={username}
            password={password}
            handleUsernameChange={({target}) => setUsername(target.value)}
            handlePasswordChange={({target}) => setPassword(target.value)}
            handleSubmit={handleLogin}
          />
        </div>
      </div>
    )
  }


  const handleTitleChange = (event) => {
    console.log(event.target.value)
    setTitle(event.target.value)
  }


  const blogForm = () => {
    return (
      <div>
        <BlogForm
          title={title}
          author={author}
          url={url}
          handleTitleChange={handleTitleChange}
          handleAuthorChange={({target}) => setAuthor(target.value)}
          handleUrlChange={({target}) => setUrl(target.value)}
          onSubmit={handleCreateBlog}
        />

      </div>
    )
  }

  const handleLogout = async () => {
    window.localStorage.clear()
    setUser(null)
  }


  const logout = () => {
    return (
    <div><button type="reset" onClick={handleLogout}>Logout</button></div>
    )}

  const blogList = () => {
    return (
      <div>
        <h2>Blogs</h2>
        <p>{user.name} logged in</p>
        {logout()}
        {blogs.map(blog => 
        <Blog 
        key={blog.id} 
        deleteBlog={() => deleteBlogId(blog.id)}
        blog={blog} 
        increment={() => incrementLike(blog.id)} />
        )}
      </div>
    )
  }

  return (
    <div className="App">

    {user === null ?

      loginForm() :
      <div>
        <Notification message={errorMessage}/>
        {blogForm()}
        {blogList()}
      </div> 
    }
    </div>
  );
}

export default App;

检查incrementLikes函数。我觉得这是有问题的。图标按钮位于名为Blog.js的组件中。

Blog.js

代码语言:javascript
运行
复制
import React from 'react';


const Blog = ({blog, increment, deleteBlog}) => (
    <div>
        <button onClick={deleteBlog}>Delete</button> 
                {blog.title} 
                {blog.author} 
                {blog.likes} 
        <button onClick={increment}>Like</button>
    </div>
)

export default Blog
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-12-27 14:42:24

虽然不应该有两个ID相同的博客,但您可以通过这样将blog.id的密钥替换为post的index来解决当前的问题。

代码语言:javascript
运行
复制
<div>
    <h2>Blogs</h2>
    <p>{user.name} logged in</p>
    {logout()}
    //change
    {blogs.map((blog,index) => 
    <Blog 
    //change
    key={index} 
    deleteBlog={() => deleteBlogId(blog.id)}
    blog={blog} 
    increment={() => incrementLike(blog.id)} />
    )}
</div>

我将//change添加到我更改的行中。

票数 3
EN

Stack Overflow用户

发布于 2019-12-27 16:20:54

您只需使用像uuid这样的东西就可以生成唯一的ID。

代码语言:javascript
运行
复制
import uuid from "uuid";

<>
  <h2>Blogs</h2>
  <p>{user.name} logged in</p>
  {logout()}
  {blogs.map((blog,index) => 
    <Blog 
      key={uuid.v4()} 
      deleteBlog={() => deleteBlogId(blog.id)}
      blog={blog} 
      increment={() => incrementLike(blog.id)} />
    )}
</>
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59502203

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档