首页 > 解决方案 > 反应原生参考 measureLayout

问题描述

我正在关注本教程

https://www.youtube.com/watch?v=ZiSN9uik​​6OY&list=RDCMUCTcH04SRuyedaSuuQVeAcdg&start_radio=1&t=1398

问题是当我 console.log(i.ref.current) 时,我看到了所有的价值。该应用程序不会以Undefined is not an Object应用程序内的错误开始。

并在反应式本机控制台中出现

This error is located at:
    in Tabs (at App.js:118)
    in RCTView (at View.js:34)
    in View (at App.js:91)
    in App (at renderApplication.js:47)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:107)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:134)
    in AppContainer (at renderApplication.js:40)
 ERROR  TypeError: undefined is not an object (evaluating 'nativeNode._nativeTag')


下面是 app.js 文件:

import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, Dimensions, Animated, FlatList, Image } from 'react-native';


const {width, height} = Dimensions.get('screen')

const images = {
  man:
    'https://images.pexels.com/photos/3147528/pexels-photo-3147528.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
  women:
    'https://images.pexels.com/photos/2552130/pexels-photo-2552130.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
  kids:
    'https://images.pexels.com/photos/5080167/pexels-photo-5080167.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
  skullcandy:
    'https://images.pexels.com/photos/5602879/pexels-photo-5602879.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
  help:
    'https://images.pexels.com/photos/6857165/pexels-photo-6857165.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500',
};
const data = Object.keys(images).map((i) => ({
  key: i,
  title: i,
  image: images[i],
  ref: React.createRef()
}));

const Indicator = () =>{
  return (<View  style={{
    position:'absolute',
    height:4,
    width:100,
    backgroundColor:'white',
    bottom: -10
   }}/>);
 
}

const Tab = React.forwardRef(({item}, ref) => {
  return (
    <View ref={ref}>
      <Text style={{
        color:'rgba(255, 255, 255, 0.8)', 
        fontWeight:'800', 
        fontSize:84/data.length,
        textTransform: 'uppercase' }}>{item.title}</Text>
    </View>
  );
});

const Tabs  = ({data, scrollX}) =>{
  const [measures, setMeasures] = React.useState([])
  const containerRef = React.useRef();

  React.useEffect(() => {
    let m = []
    data.forEach((i) => {
      i.ref.current.measureLayout(
        containerRef.current,
        (x, y, width, height) => {
          m.push({x, y, width, height})
          console.log(x, y, width, height)
        }
      );
        if(m.length === data.length){
          setMeasures(m)
        }
    });
  }, [])
  console.log(measures);
   return( <View style={{ position: 'absolute', top:50, width }}>
      <View style={{justifyContent:'space-evenly', flex:1, flexDirection:'row'}}>
        {
          data.map((item) => {
            return <Tab key={item.key} item={item} ref={item.ref} />
          }) 
        }
      </View>
      <Indicator/>
    </View>
  )

}


export default function App() {
  const scrollX = React.useRef(new Animated.Value(0)).current;


  return (
    <View style={styles.container}>
      <StatusBar hidden />
      <Animated.FlatList 
        data={data}
        keyExtractor={item => item.key}
        renderItem={({item}) => {
            return (<View style={{width, height}}>
              <Image 
                source={{uri: item.image}} 
                style={{flex:1, resizeMode:'cover'}} 
                />
                <View style={
                   [
                     StyleSheet.absoluteFillObject,
                     {backgroundColor: 'rgba(0,0,0, 0.3)' }
                   ]}/>
            </View>)
          }
        }
        horizontal
        showsHorizontalScrollIndicator={false}
        pagingEnabled
        onScroll={Animated.event([{nativeEvent: {contentOffset :{x: scrollX } }}],
          {useNativeDriver: false}
          )}
        bounces={false}
        />
        <Tabs scrollX={scrollX} data={data} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
}); ```

Thanks. appreciate your time reading this

标签: reactjsreact-nativereact-hooks

解决方案


问题是您没有附加containerRef任何View.

由于ref未附加到组件的containerRef.current计算结果为undefined,导致 中的逻辑useEffect中断。

所以你的Tabs组件应该看起来更像这样:

const Tabs = ({data, scrollX}) => {
  const [measures, setMeasures] = React.useState([]);
  const containerRef = React.useRef();

  React.useEffect(() => {
    let m = [];
    data.forEach((i) => {
      i.ref.current.measureLayout(
        containerRef.current,
        (x, y, width, height) => {
          m.push({x, y, width, height});
          console.log(x, y, width, height);
        },
      );
      if (m.length === data.length) {
        setMeasures(m);
      }
    });
  }, []);

  return (
    <View style={{position: 'absolute', top: 50, width}}>
      <View
        ref={containerRef}
        style={{justifyContent: 'space-evenly', flex: 1, flexDirection: 'row'}}>
        {data.map((item) => {
          return <Tab key={item.key} item={item} ref={item.ref} />;
        })}
      </View>
      <Indicator />
    </View>
  );
};

推荐阅读