React Native+TypeScript状态更新报错:Attempted to assign readonly property
问题分析与修复
错误原因
你遇到的问题根源在父组件的changeVal函数里:
- 直接修改了传入的
formData(也就是userDetails状态对象),React状态是不可变的,直接修改会破坏状态管理机制。 setUserDetails((formData[entry] = val))这行代码里,赋值表达式返回的是val,所以第一次更新后,userDetails会从对象变成字符串(比如你输入的用户名)。后续输入时,formData已经是字符串,字符串的属性是只读的,所以触发“Attempted to assign readonly property”错误。
修复方案
父组件修改
把changeVal改成正确的不可变更新方式,用函数式更新获取最新状态,创建新对象覆盖对应属性:
const ProfileEdit: React.FC<Props> = ({ setIsModalOpen }) => { const user = useSelector(state => state.userData.user); const [userDetails, setUserDetails] = useState({ username: user.username, firstName: user.userName, lastName: user.lastName, gender: user.gender, dateOfBirth: user.dateOfBirth, city: user.city }); // 修正后的更新函数,不需要传入formData,直接用prevState获取最新状态 const changeVal = (entry, val) => { setUserDetails(prevState => ({ ...prevState, [entry]: val })); }; return ( <Modal animationType="slide"> <Container> <EditProfileInput inputTitle="Username" changeVal={changeVal} entry="username" /> </Container> </Modal> ); };
子组件修改
不需要再传递formData,直接调用changeVal时传入entry和输入值即可:
// Child Component const EditProfileInput: React.FC<Props> = ({ inputTitle, changeVal, entry }) => { return ( <Container> <InputHeader>{inputTitle}</InputHeader> <Input> <InputText name={inputTitle} onChangeText={text => changeVal(entry, text)} /> </Input> </Container> ); };
额外说明
- 函数式更新(
setUserDetails(prevState => ...))可以确保每次更新都基于最新的状态,避免闭包导致的旧状态问题。 - 用展开运算符
...prevState创建新对象,保证状态的不可变性,符合React的状态管理规范。
内容的提问来源于stack exchange,提问作者lewisharris
相关产品推荐
相关产品推荐

