0

更新好的,所以我注意到,即使在isCategoryActive()函数中我只newCategories从 prop 分配值this.props.searchCategoriessearchCategories也会更改值,因此将其传递给连续数组项对isCategoryActive函数的调用。为什么会发生呢?更新

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

我试图在 render() 函数中获取 console.log(newCategories, url) 函数来记录:

[1] blog?categories=1
[4] blog?categories=4
[10] blog?categories=10

但目前它记录:

[1] blog?categories=1
[1,4] blog?categories=1,4
[1,4,10] blog?categories=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
4

4 回答 4

1

在你原来的功能里面有这样的:

let newCategories = this.props.searchCategories

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

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

于 2017-07-16T13:40:27.557 回答
1

代替

let newCategories = this.props.searchCategories

你可以写成

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

这将创建一个新对象。

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

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

于 2017-07-16T20:27:40.430 回答
1

问题是您this.props.searchCategories在分配时直接变异

let newCategories = this.props.searchCategories

它是通过引用分配的

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

isCategoryActive = (category) => {
    let newCategories = [..this.props.searchCategories]
    newCategories.indexOf(category) === -1
    ? newCategories.push(category)
    : newCategories.splice(newCategories.indexOf(category),1)
    return newCategories
  }
于 2017-07-16T14:23:33.183 回答
0

根据我发现的更新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
  }

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

于 2017-07-16T13:16:11.227 回答