我有一个深度为n层的集合,在最后一层,有一个数据行,其中包含一个值。显示该值很容易,但是一旦我对其进行编辑,整个集合的重新渲染将花费大量时间。
由于要对其进行编辑,因此我必须传递新值,并将项目的索引传递回最高级别。
下面的代码只是一个示例,因为我在询问可能的方法。
高级组件:
const HighComponent = () => {
const [data, setData] = useState([]); //array of objects
render <TableWithData data={data} onChange={setData}/>
}
n级深的组件:
const FinalComponent = ({item, itemsIndexInPreviousArray, onChangeFromPreviousComponent}) => {
// this kind of function will assemble the data from the lowest point and return it back
// to the highest component, that will receive the final data to change, but this kind of
// approach will take n*itemsNumber re-renders and time-wise is quiet slow.
const changeThisItem = (newValue) => {
onChangeFromPreviousComponent(newValue, itemsIndexInPreviousArray)
}
return (
<>
<input value={item} onChange={e => changeThisItem(e.target.value)}/>
</>
);
}
我将使用备忘录,但是该组件仅用于显示,并且它们必须触发端点以更新finalData(顶层数据)。无论是onChange事件还是批量触发器。
任何建议,将不胜感激。
最佳答案
需要将数据传递到多个级别(并且可能需要多个组件使用),这表明您可能需要更复杂的东西来管理状态。
您可以考虑Redux。它可以轻松愉快地解决您的问题。
请查看以下实时代码段,注意在您键入时中间组件不会重新呈现:
const { useEffect } = React,
{ render } = ReactDOM,
{ createStore } = Redux,
{ Provider, useSelector, useDispatch } = ReactRedux
const defaultState = {data:''},
appReducer = (state=defaultState, action) => {
switch(action.type){
case 'SET_DATA': {
return {...state, data: action.payload}
}
default: return state
}
},
store = createStore(appReducer)
const Parent = ({children}) => {
const data = useSelector(({data}) => data)
useEffect(() => console.log('Parent is rendered'))
return (
<div>
<div>Current data value is: {data}</div>
{children}
</div>
)
}
const Intermediate = ({children}) => {
useEffect(() => console.log('Intermediate is rendered'))
return (
<div>{children}</div>
)
}
const Child = () => {
const dispatch = useDispatch()
useEffect(() => console.log('Child is rendered'))
return (
<input
onKeyUp={({target:{value}}) => dispatch({
type: 'SET_DATA',
payload: value
})}
/>
)
}
render (
<Provider {...{store}} >
<Parent>
<Intermediate>
<Child />
</Intermediate>
</Parent>
</Provider>,
document.getElementById('root')
)
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script><script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script><script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.4/redux.min.js"></script><script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.1.1/react-redux.min.js"></script><div id="root"></div>