我有一个深度为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>

07-24 09:43
查看更多