*这不完全是我的情况,但这很重要。
想象一个渲染元素列表的应用程序:
const ElementsList = ({elements, <onElementTextChange>}) => (
<div className='ElementsList'>
{elements.map(el => (
<Element
key={el.id}
element={el}
/>
))}
</div>
)
元素保持在呈现ElementsList
的父组件的状态。每个元素都是一个简单的对象:
this.state = {elements: [
{id: 1, text: 'apple'},
{id: 23, text: 'banana'},
]}
...
render() { ... <ElementsList elements={this.state.elements}/> ... }
每个元素都会在附近的输入字段中进行渲染以更改其文本:
export const Element = ({element, <onTextChange>}) => (
<div className='Element'>
<div className='element-text'>{element.text}</div>
<input type='text' value={element.text} onChange={???}></input>
</div>
)
请考虑可能有很多元素(应用程序可以处理更多元素)。
现在的问题是,我们应该如何通过这些输入来更新文本。
我看到2个选项(可能有一些组合):
onChange={evt => onTextChange(evt.target.value)}
onTextChange={newText => onElementTextChange(el, newText)}
onElementTextChange={ (element, newText) => {make new elements array with the updated element somehow; setState(elements)} }
该解决方案似乎难以实施。与下面的替代方法相比,它也很慢。输入更改时发生事件(如果我输入错了,请纠正我):
setState
forceUpdate()
输入更改时发生的事件:
forceUpdate
目前,我正在使用一种中间方法,但更多地是在“适当的反应方式”方面。而且速度不够快。
我更喜欢第二个选项,它需要较少的代码,并且看起来应该工作得更快(理论上)。
答案 0 :(得分:1)
不变的数据结构通过备忘录和结构共享之类的技术解决了您的性能问题。
您应该考虑使用Immutable.js。然后,您可以使用React.PureComponent对大型数据结构进行有效的值相等检查。
一个缺点是Immutable.js数据结构与常规可变javascript数据结构不能很好地混合,这可能令人沮丧。诸如Elm或ClojureScript之类的某些语言为此类数据结构提供了一流的支持,使其体验更加一致。
答案 1 :(得分:1)
你可以这样做
this.state = {elements: [
{id: 1, text: 'apple'},
{id: 23, text: 'banana'},
]}
// creating a update function which you will pass down to the child
updateState = (id, val) => {
const newElements = this.state.elements;
newElements.map(item => {
if(item.id === id) item.text = val;
});
this.setState({
elements: newElements,
})
}
render() { ... <ElementsList elements={this.state.elements} updateState ={this.updateState}/> ... }
现在在ElementsList中
const ElementsList = ({elements, updateState, <onElementTextChange>}) => (
<div className='ElementsList'>
{elements.map(el => (
<Element
key={el.id}
element={el}
updateState = {updateState}
/>
))}
</div>
)
现在在元素中
export class Element extends React.Component{
state = {
value: '',
}
onChangeValue = (e) => {
this.setState({ value: e.target.value});
// calling the parent function directly
this.props.updateState(this.props.element.id, e.target.value);
}
componentDidMount(){
this.setState({
value: this.props.element.text,
})
}
render(){
return(
<div className='Element'>
<div className='element-text'>{element.text}</div>
<input type='text' value={this.state.value} onChange={this.onChangeValue}></input>
</div>
)
}
}