Компонент, возвращающий пользовательский хук, перерисовывает все дочерние элементы, если изменяется индивидуальное состояние хука - PullRequest
0 голосов
/ 30 апреля 2020

Почему при использовании пользовательского хука для рендеринга компонента перерисовывается компонент приложения. Если я переключу <Comp> or <AnotherComp>, то весь компонент приложения будет перерисован одинаково для другого компонента.

Я попробовал React.memo и снова обернул компонент в компонент приложения, но безрезультатно.

Я прочитал то, как реагирует, сравнивает и рассматривает различные функции. Но есть ли продвинутый шаблон, который люди используют для этой цели?

export const useCard = (params)=>{
const { ToBeWrappedComponent } = params;
const [isOpen,setIsOpen] = useState(true);

const toggle= ()=> setIsOpen(!isOpen);

const WrappedComponent = ()=>{ 
return (
<Collapse isOpen={isOpen} >
<button onClick= {toggle}> </button>
<ToBeWrappedComponent />
</Collapse>
)
}

return [WrappedComponent,toggle]
};



const App = ()=>{
const [Comp, toggleComp] = useCard({ToBeWrappedComponent: ()=> (<h1>Wrapped Item <h1>) });
const [AnotherComp, toggleAnotherComp] = useCard({ToBeWrappedComponent: ()=> (<h1>Another Wrapped Item <h1>) })

return (
<AnotherComp > </AnotherComp>
<Comp> </Comp>
)
}

Обратите внимание, что этот код является лишь примером, который я создал, чтобы продемонстрировать, с чем я сталкиваюсь, я делаю более сложные вещи с этим apporach и просто хочу узнать о шаблонах Advanced, чтобы достичь его, и о причине рендеринг. Спасибо

1 Ответ

1 голос
/ 01 мая 2020

Поскольку этот вызов useState фактически вызывается в функции компонента приложения:

const [isOpen,setIsOpen] = useState(true);

Таким образом, он становится частью состояния App, а не состояния обернутого компонента.

Компонент перерисовывается, потому что каждый раз, когда приложение перерисовывается, функция WrappedComponent создается заново. Это другая функция с другим адресом в памяти, и поэтому дерево компонентов перерисовывается с нуля.

Это действительно странный шаблон, который вы используете. Вы действительно усложняете вещи. Почему бы просто не передать функцию рендеринга компоненту-оболочке?

const TogglableComponent = ({ renderWrappedComponent, isOpen, onClick }) => { 
  return (
    <Collapse isOpen={isOpen} >
      <button onClick={onClick} />
      { renderWrappedComponent() }
    </Collapse>
  )
};

Затем вы управляете состоянием переключения каждого компонента из его родительского элемента через подпорки. Или, если вам не нужно передавать состояние переключения родительскому компоненту, просто сохраните его в оболочке:

const TogglableComponent = ({ renderWrappedComponent }) => {
  const [isOpen, setIsOpen] = React.useState(false);
  return (
    <Collapse isOpen={isOpen} >
      <button onClick={() => setIsOpen(!isOpen)} />
      { renderWrappedComponent() }
    </Collapse>
  )
};
...