Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/441.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在发生突变的反应组分中加入Prop_Javascript_Reactjs - Fatal编程技术网

Javascript 在发生突变的反应组分中加入Prop

Javascript 在发生突变的反应组分中加入Prop,javascript,reactjs,Javascript,Reactjs,我有一个奇怪的场景,反应组件中的道具正在发生变异。它是一个数组,所以从技术上讲它不是一个变种(在JavaScript领域),但仍然没有办法修改它 我已经做了一个简单的例子来复制这个问题。 此组件: 接受包含初始“组”数据的道具 允许您过滤该组数据(通过文本框) 将状态属性设置为筛选的组数据 然后并排显示初始道具数据和过滤后的状态数据 组数据是组的列表,每个组都有一个名称和一个子对象数组。这些子对象将表示人员{name:[value]},或多个组,形成层次结构 组数据的筛选操作正确。但是,由于某

我有一个奇怪的场景,反应组件中的道具正在发生变异。它是一个数组,所以从技术上讲它不是一个变种(在JavaScript领域),但仍然没有办法修改它

我已经做了一个简单的例子来复制这个问题。

此组件:

  • 接受包含初始“组”数据的道具
  • 允许您过滤该组数据(通过文本框)
  • 将状态属性设置为筛选的组数据
  • 然后并排显示初始道具数据和过滤后的状态数据
  • 组数据是组的列表,每个组都有一个名称和一个子对象数组。这些子对象将表示人员
    {name:[value]}
    ,或多个组,形成层次结构

    组数据的筛选操作正确。但是,由于某些原因,状态和道具都会更新

    以下是JS:

    /**
     * Define the component.
     */
    class TestComponent extends React.Component {
      constructor(props) {
        super(props)
    
        const {initialGroups} = this.props
    
        //Initialize filtered groups with the intial groups
        this.state = {
          filteredGroups: initialGroups
        }
      }
    
      /**
       * Simply outputs the props and the state to the screen,
       * as well as an input field that filters the group data.
       */
      render() {
        return (
          <div>
            <input type="text" placeholder="Filter by name" onChange={onChange.bind(this)} />
            <section id="output">
              <pre>
                <h1>props:</h1>
                {JSON.stringify(this.props,null,2)}
              </pre>
              <pre>
                <h1>state:</h1>
                {JSON.stringify(this.state,null,2)}
              </pre>
            </section>
          </div>
        )
      }
    }
    
    TestComponent.propTypes = {
      initialGroups: React.PropTypes.array.isRequired
    }
    
    /**
     * Define event handler for text input change, 
     * which filters group data recursively,
     * the result of which gets saved in state.
     */
    function onChange(e) {
      //Get input value
      const filterInputValue = e.target.value
    
      //Get initial group data to filter. Note how this is copying the array, non-mutatingly, just in case.
      const initialGroups = [...this.props.initialGroups] 
    
      //Filter the group data (function defined below).
      const filteredGroups = filterGroupsByPerson(initialGroups) 
    
      //Update the state
      this.setState({filteredGroups})
    
      //Recursive filtering function
      function filterGroupsByPerson(arr) {
        return arr.filter(item=>{
          const hasChildren = item.children instanceof Array && item.children.length > 0
    
          //Having children implies this is a group. Don't test the name, just try to filter the children.
          if(hasChildren) {
            //Filter children array recursively
            item.children = filterGroupsByPerson(item.children) 
            return item.children.length > 0
          }
    
          //This is a person, not a group. Filter on the name.
          const filterRegex = new RegExp(filterInputValue, 'i')
          const filterResults = filterRegex.test(item.name)
          return filterResults
        })
      }
    }
    
    /**
     * Mock up the initial group data
     */
    const InitialGroups = [
      {
        "name": "Engineering",
        "children": [
          {"name": "Gates"},
          {"name": "Allen"},
          {"name": "Jobs"},
          {"name": "Wozniak"},
          {
            "name": "Consultants",
            "children": [
              {"name": "Jess"},
              {"name": "Cece"},
              {"name": "Winston"},
              {"name": "Schmidt"}
            ]
          },
        ]
      }
    ]
    
    /**
     * Implement component, passing initial group data as a prop.
     */
    ReactDOM.render(<TestComponent initialGroups={InitialGroups}/>, document.getElementById('test-component'))
    
    你可以做:

    此处的工作笔

    您可以执行以下操作:


    此处的工作笔

    […this.props.initialGroups]
    仅执行浅层复制。数组中的对象不会被复制,因此出现这种效果的原因是
    item.children=filterGroupsByPerson(item.children)
    。换句话说:道具和状态似乎都在更新,因为它们引用同一个对象。看起来你想进行深度复制。为什么不呢。。。。。。你是说新数组中的项是对旧数组中相同项的引用吗?是的。如果你有
    varfoo=[{x:42}]
    var-bar=[…foo]然后
    foo[0]==bar[0]
    true
    。更改
    bar[0].x
    将影响
    foo
    ,因为
    foo[0]
    bar[0]
    引用了同一个对象。这实际上不是特别优雅,而且依赖于字符串解析;为什么不使用任何现有的
    clone
    实现(lodash,无论什么)?
    […this.props.initialGroups]
    只执行浅拷贝。数组中的对象不会被复制,因此出现这种效果的原因是
    item.children=filterGroupsByPerson(item.children)
    。换句话说:道具和状态似乎都在更新,因为它们引用同一个对象。看起来你想进行深度复制。为什么不呢。。。。。。你是说新数组中的项是对旧数组中相同项的引用吗?是的。如果你有
    varfoo=[{x:42}]
    var-bar=[…foo]然后
    foo[0]==bar[0]
    true
    。更改
    bar[0].x
    将影响
    foo
    ,因为
    foo[0]
    bar[0]
    引用了同一个对象。这实际上不是特别优雅,而且依赖于字符串解析;为什么不使用任何现有的
    clone
    实现(lodash,随便什么)?
    <div id="test-component"></div>
    
    #output {
      display:flex;
    }
    
    #output pre {
      background-color: #eeeecc;
      margin-right: 20px;
    }
    
    const filterInputValue = e.target.value
      const intialGroupClone = JSON.parse(JSON.stringify(this.props.initialGroups))
    
      const filteredGroups = filterGroupsByPerson(intialGroupClone) 
    
      //Update the state
      this.setState({filteredGroups})