Как повторно отрендерить родительский компонент после получения дочерней ссылки с помощью хука useRef?

Я бью головой, пытаясь решить одну досадную проблему:

У меня есть родительский компонент и дочерний. У ребенка есть абсолютное позиционирование и динамический рост. Мне нужно рассчитать размер родительского поля в зависимости от роста ребенка. Я пытался сделать что-то вроде

const Parent = () => {
  const childRef = useRef(null);
  return (
     <Child saveRef={ref} />
);

const Child = ({saveRef}) => (<div ref={saveRef}> </div>);

Но проблема в том, что родительский компонент не перерисовывается при выполнении Ref. Как я могу повторно отрендерить родительский компонент после получения Ref?

Заранее благодарим за любую помощь и совет.


person Mike Yermolayev    schedule 16.02.2019    source источник


Ответы (2)


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

const Parent = () => {
  const childRef = useRef(null);
  const [margin, updateMargin] = useState(0);
  useEffect(() => {
     // calculate margin. Let call it margin
     updateMargin(margin);
  }, []);

  return (
     <Child saveRef={ref} />
);

const Child = ({saveRef}) => (<div ref={saveRef}> </div>);

РЕДАКТИРОВАТЬ: для обновления при изменении размера окна вам необходимо добавить прослушиватель событий при изменении размера окна и пересчитать высоту.

const Parent = () => {
  const childRef = useRef(null);
  const [margin, updateMargin] = useState(0);
  useEffect(() => {
     window.addEventListener('resize', handleResize);
     () => {
         window.removeEventListener('resize', handleResize);
     }
  }, []);

  const handleResize = () => {
       // use ref, calcualte margin and update
  }
  return (
     <Child saveRef={ref} />
);
person Shubham Khatri    schedule 16.02.2019
comment
Поскольку эффект включает DOM, возможно, это касается useLayoutEffect. - person Estus Flask; 16.02.2019
comment
Пришел к тому же решению, что и предложил @estus. Но теперь я борюсь с другой проблемой) При изменении размера окна мне нужно снова пересчитать высоту - person Mike Yermolayev; 16.02.2019
comment
@MikeErmolaev Обновил ответ - person Shubham Khatri; 16.02.2019

Вы можете передать функцию в качестве опоры дочернему элементу от родителя и вызвать эту функцию, когда вам нужно повторно отрисовать родительский элемент. Изменение состояния вызовет рендеринг. Итак, в функции вы можете просто изменить состояние.

class Parent extends React.Component{
 state = {ref : null}

 handleRef = ref => {
  this.setState({ ref });
  // your add you method for changing margin
 }

 render(){
   return <Child ref={this.state.ref} handleRefChange={this.handleRef} />
 }
}

Сохраните ссылку в родительском компоненте и вызовите handleRefChange из дочернего компонента, чтобы обновить его.

person Vishnu    schedule 16.02.2019