Javascript数组映射函数保留数组先前项目的记录



update 好的,所以我注意到,即使在isCategoryActive()函数中,我也只改变了从this.props.searchCategories分配值的变量newCategoriessearchCategoriesprop 也会更改值,因此将其传递给连续数组项对isCategoryActive函数的调用。为什么会这样??更新

我正在基于 Wordpress REST API 在 React 中构建博客的前端,并且在检查帖子类别是否已被过滤后创建链接以过滤帖子类别时遇到问题。我遇到的问题是,即使我在map函数中编写了一个纯函数isCategoryActive每个连续的类别链接URL中都有每个前面的类别ID。我本以为每次调用纯函数时我都会收到一个干净的结果,但就我而言,情况并非如此。目前,wordpress存储3个类别:ID:1的"未分类" id: 4 的 "JavaScript", ID为:10的"第三类">

我试图让 render() 函数中的 console.log(newCategories, url) 函数记录:

[1] 博客类别=1
[4] 博客类别=4
[10] 博客类别=10

但目前它记录:

[1] 博客类别=1[1,4] 博客类别=1,4[1,4,10] 博客类别=1,4,10

我不知道为什么它保留以前类别 ID 的记录。

代码如下:

// import dependencies
import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import axios from 'axios'
// import components
import '../Styles/Css/PostsCategories.css'
import { createSearchUrl } from './SharedModules'
class PostsCategories extends Component {
constructor() {
super()
this.state = {
categories: null,
loading: false
}
}
componentDidMount() {
this.setState({
loading: true
})
axios.get(`http://localhost/wordpress-api/wp-json/wp/v2/categories`)
.then(res => {
this.setState({
categories: res.data,
loading: false
})
})
}
isCategoryActive = (category) => {
let newCategories = this.props.searchCategories
newCategories.indexOf(category) === -1
? newCategories.push(category)
: newCategories.splice(newCategories.indexOf(category),1)
return newCategories
}
render() {
if (this.state.loading || !this.state.categories) return <div className='posts-categories'><h2 className='loading'>Loading ...</h2></div>
const categories = this.state.categories.map(category => {
const newCategories = this.isCategoryActive(category.id)
const url = createSearchUrl('/blog', newCategories, this.props.searchString)
console.log(newCategories, url)
return (
<Link
to={url}
onClick={this.props.searchCategoryChange.bind(this, category.id)}
className='posts-category'
key={category.id} >
{category.name}
</Link>
)})
return (
<div className='posts-categories'>
{categories}
</div>
)
}
}
export default PostsCategories

在你的原始函数中是这样的:

let newCategories = this.props.searchCategories

这实际上不会复制searchCategories而是引用它。它们都指向同一个数组,这就是为什么原始searchCategories数组也被修改的原因。

当您映射searchCategories数组时(就像您在自己的解决方案中所做的那样),您将在不修改searchCategories数组的情况下构建一个新数组(使用 push 语句)。然而,这是一种非常复杂的数组副本制作方法。

问题是你直接从this.props.searchCategories变异,因为你

分配
let newCategories = this.props.searchCategories

它是通过引用分配的

您需要创建一个新对象,而不是直接分配它。为此,您可以使用 spread 运算符,而不是映射在 propsarray并将项目推送到数组newCategories

isCategoryActive = (category) => {
let newCategories = [..this.props.searchCategories]
newCategories.indexOf(category) === -1
? newCategories.push(category)
: newCategories.splice(newCategories.indexOf(category),1)
return newCategories
}

而不是

let newCategories = this.props.searchCategories

你可以写成

let newCategories = this.props.searchCategories.splice();

这将创建一个新对象。

默认情况下,JavaScript 仅在我们直接分配对象(以及数组)时复制引用。也就是说,当新对象更改时,原始对象也会更改。

您必须使用 map、splice 或 Object.assign 来创建新对象。

根据我发现的更新中的新信息,我将isCategoryActive函数修改为:

isCategoryActive = (category) => {
let newCategories = []
this.props.searchCategories.map(category => newCategories.push(category))
newCategories.indexOf(category) === -1
? newCategories.push(category)
: newCategories.splice(newCategories.indexOf(category),1)
return newCategories
}

现在它运行良好。但是,我仍然不完全理解为什么它以前存储以前的记录。我想我错过了一些非常愚蠢的东西,但如果有人能向我描述最初的根本问题,那就太好了。

最新更新