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