reactjs - วิธีการพิมพ์ measureLayout อย่างถูกต้องใน react-native
ฉันต้องการตั้งความสูงของ SVG ให้ใช้พื้นที่เฉพาะที่ฟอร์มด้านล่างอนุญาต เพื่อให้ทุกองค์ประกอบพอดีในหน้าต่างมุมมอง สำหรับเรื่องนั้น ฉันได้ส่งต่อ ref ไปยังคอมโพเนนต์ฟอร์มและคำนวณขนาดที่ควรใช้ด้วยฟังก์ชัน measureLayout ตามเอกสาร
measureLayout(relativeToNativeComponentRef, onSuccess, onFail) คล้ายกับ measure() แต่จะวัดมุมมองโดยสัมพันธ์กับบรรพบุรุษ ซึ่งกำหนดโดยการอ้างอิง relativeToNativeComponentRef ซึ่งหมายความว่าพิกัดที่ส่งคืนจะสัมพันธ์กับจุดกำเนิด x, y ของมุมมองบรรพบุรุษ
และตัวอย่างแสดงให้เห็นว่าพวกเขาเพียงแนบ refs สองตัวกับพ่อแม่และลูกด้วยค่าเริ่มต้นเป็น null และมันก็ทำงานได้
ใน TypeScript อาร์กิวเมนต์ตัวแรก - relativeToNativeComponentRef มีประเภทเป็น RefObject
const { height: viewportHeight } = Dimensions.get("window");
export const Home: React.FC<HomeScreenProps> = ({ navigation }) => {
const [svgHeight, setSvgHeight] = useState(0);
const svgHeightForwardedRef = useRef<View | null>(null);
const dispatch = useAppDispatch();
const onSumbit = (data: UserMetrics) => {
const { gender, age } = data;
dispatch(setUserData(data));
navigation.navigate("Tests", { gender, age });
};
const homeScreenContainerRef = useRef<number | HostComponent<unknown>>(null);
useLayoutEffect(() => {
if (svgHeightForwardedRef.current && homeScreenContainerRef.current) {
svgHeightForwardedRef.current?.measureLayout(
homeScreenContainerRef.current,
(left, top, width, height) => {
console.log(left, top, width, height);
const svgHeightPerPlatform =
Platform.OS === "web"
? viewportHeight - height + top
: viewportHeight - height - top;
setSvgHeight(svgHeightPerPlatform);
},
() => {
console.log("fail");
}
);
}
}, [svgHeightForwardedRef, homeScreenContainerRef]);
return (
<View style={styles.container} ref={homeScreenContainerRef}>
<View style={styles.wrapper}>
<StatusBar style="auto" />
<Text style={styles.welcomeText}>Test Reminder</Text>
<View style={styles.heroWrapper}>
<HeroSVG
width={PLATFORM_WIDTH}
height={svgHeight}
preserveAspectRatio="xMidYMid meet"
/>
</View>
<HealthCheckForm onSubmit={onSumbit} ref={svgHeightForwardedRef} />
</View>
</View>
);
};
ขอบคุณมาก
แก้ไข: ฉันได้แก้ไข "และนอกจากนี้ในตอนโหลดครั้งแรกค่าทั้งหมดจะเป็น 0 0 0 0 เท่านั้น เมื่อฉันรีเฟรชด้วยตนเองมันจะแสดงผลอย่างถูกต้อง คุณสามารถให้คำใบ้เกี่ยวกับเรื่องนั้นได้ไหม?" โดยการใส่ [svgHeightForwardedRef.current, homeScreenContainerRef.current] ในอาร์เรย์ของ dependency แทนที่จะเป็น [svgHeightForwardedRef, homeScreenContainerRef] แต่ฉันยังต้องการความช่วยเหลือในเรื่อง TypeScript อยู่ ขอบคุณ
คำตอบ #1
ใช้ findNodeHandle เพื่อแปลงประเภทของ ref
import {findNodeHandle, StyleSheet, Text, View} from 'react-native';
export const Home: React.FC<any> = ({}) => {
const textContainerRef = useRef<View>(null);
const textRef = useRef<Text>(null);
const [measure, setMeasure] = useState<{
left: number;
top: number;
width: number;
height: number;
} | null>(null);
useEffect(() => {
const textRefHandle = findNodeHandle(textContainerRef.current);
if (textRef.current && textRefHandle) {
textRef.current.measureLayout(
textRefHandle,
(left, top, width, height) => {
setMeasure({left, top, width, height});
},
() => console.log('fail'),
);
}
}, [measure]);
return (
<View style={styles.container}>
<View ref={textContainerRef} style={styles.textContainer}>
<Text ref={textRef}>Where am I? (relative to the text container)</Text>
</View>
<Text style={styles.measure}>{JSON.stringify(measure)}</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
textContainer: {
backgroundColor: '#61dafb',
justifyContent: 'center',
alignItems: 'center',
padding: 12,
},
measure: {
textAlign: 'center',
padding: 12,
},
});
