如何从子组件更新父函数组件的状态?
问题分析与解决方案
核心问题
- 索引参数传递错误:父组件渲染
Item时未传递数组索引,子组件误用React内部的key属性作为业务索引,导致更新时找不到正确的数组项。 - 子组件状态与父组件不同步:父组件数据更新后,子组件本地
text状态未同步titleprops的变化,显示内容不一致。 - 无效的useEffect触发:初始化阶段
useEffect就调用onEdit,会错误覆盖父组件初始状态。
修复后的完整代码
import React, { useState, useEffect } from 'react'; import { SafeAreaView, View, StyleSheet, Text, StatusBar, TouchableOpacity, Modal, TextInput, Pressable } from 'react-native'; const App = () => { const FRUITS = [{ name: 'Banana', }, { name: 'Pineapple', }, { name: 'Strawberry', }]; const [data, setData] = useState(FRUITS); const _addNew = () => { const dataCpy = [...data]; dataCpy.push({ name: 'Another item', }); setData(dataCpy); }; const _onEdit = (edit, ind) => { const dataCpy = [...data]; dataCpy[ind] = {name: edit}; setData(dataCpy); }; return ( <SafeAreaView style={styles.container}> { data.map((item: any, ind: number) => <Item title={item.name} key={ind} index={ind} onEdit={_onEdit} />) } <Pressable style={styles.button} onPress={_addNew}> <Text style={styles.buttonTextLarge}> + Add new item</Text> </Pressable> </SafeAreaView> ); }; export default App; const Item = ({ title, index, onEdit }: { title: string, index: number, onEdit: (edit: string, ind: number) => {} }) => { const [text, onTitleChanged] = useState(title); const [modalVisible, setModalVisible] = useState(false); // 同步父组件传来的title变化到本地状态 useEffect(() => { onTitleChanged(title); }, [title]); const _toggleModal = () => { setModalVisible(!modalVisible); }; const _onFinishEdit = () => { onEdit(text, index); _toggleModal(); }; return (<> <TouchableOpacity onPress={ _toggleModal }> <View style={styles.item}> <Text style={styles.title}>{title}</Text> </View> </TouchableOpacity> <Modal transparent={true} visible={modalVisible} onRequestClose={ _toggleModal }> <View style={styles.centeredView}> <View style={styles.modalView}> <TextInput style={styles.input} onChangeText={onTitleChanged} placeholder="useless placeholder" value={text} /> <Pressable style={[styles.button, styles.buttonClose]} onPress={_onFinishEdit}> <Text style={styles.buttonText} >Finish edit</Text> </Pressable> </View> </View> </Modal> </>); }; const styles = StyleSheet.create({ container: { flex: 1, marginTop: StatusBar.currentHeight || 0, margin: 6, }, item: { backgroundColor: '#00c2fe', padding: 12, borderRadius: 3, marginVertical: 8, marginHorizontal: 3, }, title: { fontSize: 32, }, input: { height: 40, margin: 12, borderWidth: 1, padding: 10, }, centeredView: { flex: 1, justifyContent: 'center', alignItems: 'center', marginTop: 22, }, modalView: { margin: 20, backgroundColor: 'white', borderRadius: 20, padding: 35, alignItems: 'center', shadowColor: '#000', shadowOffset: { width: 0, height: 2, }, shadowOpacity: 0.25, shadowRadius: 4, elevation: 5, }, button: { borderRadius: 3, padding: 9, elevation: 2, marginTop: 15, backgroundColor: '#5bddb9', }, buttonClose: { backgroundColor: '#2196F3', }, buttonText: { fontSize: 12, fontWeight: "bold", }, buttonTextLarge: { fontSize: 24, fontWeight: "bold", }, });
关键修复点
- 传递正确索引:父组件
map遍历给Item传递index={ind}属性,子组件接收index作为业务索引,不再误用key。 - 同步父组件状态:子组件添加
useEffect监听titleprops变化,实时更新本地text状态,确保父子组件数据一致。 - 移除无效逻辑:删除初始化时自动触发的
useEffect,仅保留完成编辑时手动调用onEdit的逻辑,避免初始状态被错误覆盖。
内容的提问来源于stack exchange,提问作者Monero Jeanniton
相关产品推荐
相关产品推荐

