gpt4 book ai didi

javascript - React 中的重复键无法解决问题。遇到两个 child 拥有同一把 key

转载 作者:行者123 更新时间:2023-12-01 00:20:01 25 4
gpt4 key购买 nike

错误:

Warning: Encountered two children with the same key, 5e0611d77833da1668feade1. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.

在这张图片上 https://prnt.sc/qgfymk 我创建了 2 个博客。删除按钮工作正常。我使用 mongoose 和 MongoDB 作为数据库通过 axios 发送 HTTP 删除请求。

但是当我开始点击“喜欢”按钮时,请检查会发生什么。 <强> https://prnt.sc/qgg32o 它删除了我的另一篇博文并复制了一篇具有相同名称和 ID 的博文。这里的问题是我有不同的 ID,但不知怎的,当我按 LIKE 按钮时,它给了我另一个 ID。

我会给你后端 PUT 请求和增量喜欢前端的代码,我真的不知道发生了什么。

controllers/blogs.js(后端)

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

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 的组件中

博客.js

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

最佳答案

虽然不应该有 2 个具有相同 ID 的博客,但您可以通过将 blog.id 中的 key 替换为帖子的 index 来解决当前的问题像这样。

<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 添加到我更改的行中。

关于javascript - React 中的重复键无法解决问题。遇到两个 child 拥有同一把 key ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59502203/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com