React Native onLayout с помощью React Hooks - PullRequest
1 голос
/ 24 июня 2019

Я хочу измерить размер React Native View каждый раз, когда он рендерится, и сохранить его в состояние. Если расположение элементов не изменилось, эффект не должен запускаться.

Это легко сделать с помощью компонента на основе классов, где можно использовать onLayout . Но что мне делать в функциональном компоненте, где я использую React Hooks?

Я читал о useLayoutEffect . Если это путь, у вас есть пример, как его использовать?

Я сделал этот пользовательский хук, который называется useDimensions. Вот как далеко у меня:

const useDimensions = () => {
  const ref = useRef(null);
  const [dimensions, setDimensions] = useState({});
  useLayoutEffect(
    () => {
      setDimensions(/* Get size of element here? How? */);
    },
    [ref.current],
  );
  return [ref, dimensions];
};

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

const [ref, dimensions] = useDimensions();

return (
  <View ref={ref}>
    ...
  </View>
);

Я пытался отладить ref.current, но не нашел там ничего полезного. Я также пробовал measure () внутри хука эффекта:

ref.current.measure((size) => {
  setDimensions(size); // size is always 0
});

1 Ответ

2 голосов
/ 25 июня 2019

У вас была правильная идея, просто потребовалась пара настроек ... в основном, передача элемента ref и использование elementRef (не elementRef.current) в массиве зависимостей useEffect.

(Что касается useEffect против useLayoutEffect, поскольку вы только измеряете, а не мутируете DOM, то я считаю, что useEffect - это путь к , но вы можете поменять его, как ... например, если вам нужно)

const useDimensions = elementRef => {
   const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
   useEffect(() => {
      const el = elementRef.current;
      setDimensions({ width: el.clientWidth, height: el.clientHeight });
    }, [elementRef]);
    return [dimensions];
};

Используйте это так:

function App() {
  const divRef = useRef(null);
  const [dimensions] = useDimensions(divRef);
  return (
    <div ref={divRef} className="App">
      <div>
        width: {dimensions.width}, height: {dimensions.height}
      </div>
    </div>
  );
}

Рабочие коды и коробка здесь

Отредактировано для добавления React Собственная версия:

Для React Native вы можете использовать useState с onLayout следующим образом:

const App=()=>{
  const [dimensions, setDimensions] = useState({width:0, height:0})
    return (
      <View onLayout={(event) => {
                const {x, y, width, height} = event.nativeEvent.layout;
                setDimensions({width:width, height:height});
        }}>
        <Text}>
          height: {dimensions.height} width: {dimensions.width}
        </Text>
      </View>
    );

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...