React Native跨组件修改状态:Todo应用Modal无法关闭
问题分析与解决方案
问题根源
你在AddTodo和GetInfoDialog中分别调用了useChange自定义Hook,每次调用Hook都会生成独立的状态实例。也就是说,GetInfoDialog里修改的state是它自己的局部状态,和AddTodo中控制Modal显示的state完全无关,所以点击Cancel按钮无法关闭弹窗。
解决方案
将AddTodo中的状态控制逻辑通过props传递给GetInfoDialog,让子组件直接调用父组件的状态修改方法,确保操作的是同一个状态。
修改后的AddTodo.js
import { Modal, StyleSheet, Text, TouchableOpacity, View } from "react-native"; import { GetInfoDialog } from "./GetInfoDialog"; import { React, useState } from "react"; function useChange() { const [state, setState] = useState(false); function change(value) { setState(value); console.log("state: " + value); } return { state, change }; } function AddTodo() { const { state, change } = useChange(); return ( <View style={styles.container}> <Modal animationType="slide" transparent={true} visible={state} style={styles.itemsContainer} > {/* 将关闭弹窗的方法通过props传给子组件 */} <GetInfoDialog onCancel={() => change(false)} /> </Modal> <TouchableOpacity style={styles.btn} onPress={() => { change(true); }} > <Text style={styles.text}>Add New</Text> </TouchableOpacity> </View> ); } // 补充样式(根据你的需求调整) const styles = StyleSheet.create({ container: { margin: 16, }, btn: { backgroundColor: "#2196F3", padding: 12, borderRadius: 8, alignItems: "center", }, text: { color: "#fff", fontSize: 16, fontWeight: "500", }, itemsContainer: { flex: 1, justifyContent: "center", alignItems: "center", }, }); export default AddTodo;
修改后的GetInfoDialog.js
import React, { useState } from "react"; import { StyleSheet, Text, TextInput, TouchableOpacity, View, } from "react-native"; // 通过props接收父组件传递的关闭方法 function GetInfoDialog({ onCancel }) { return ( <View style={styles.container}> <Text style={styles.headerText}>Add Todo</Text> <TextInput style={styles.input} placeholder="Enter todo content" /> <View style={styles.btnContainer}> <TouchableOpacity style={styles.btn}> <Text style={styles.text}>Add</Text> </TouchableOpacity> <TouchableOpacity style={styles.btn} onPress={onCancel} // 直接调用父组件传来的关闭方法 > <Text style={styles.text}>Cancel</Text> </TouchableOpacity> </View> </View> ); } // 补充样式(根据你的需求调整) const styles = StyleSheet.create({ container: { backgroundColor: "#fff", padding: 24, borderRadius: 12, width: "80%", alignItems: "center", }, headerText: { fontSize: 20, fontWeight: "bold", marginBottom: 16, }, input: { borderWidth: 1, borderColor: "#ccc", borderRadius: 8, padding: 12, width: "100%", marginBottom: 16, }, btnContainer: { flexDirection: "row", gap: 12, }, btn: { backgroundColor: "#2196F3", padding: 12, borderRadius: 8, alignItems: "center", width: 80, }, text: { color: "#fff", fontSize: 16, }, }); export default GetInfoDialog;
额外注意点
- 修正了
GetInfoDialog.js中import react的拼写错误,改为import React(首字母大写),避免React Native报错。 - 给两个组件都添加了
export default,确保组件能被正确引用。
内容的提问来源于stack exchange,提问作者Kuber D
相关产品推荐
相关产品推荐

