我有一个Flatlist组件,该组件将其状态和setState传递给子组件。子组件确实会更改父组件的状态(尝试使用setinterval和console.log显示状态),但是发生更改时我听不到。我尝试使用
useEffect(()=>{
console.log(`listState:`, state);
},[state]);
但是它永远不会在安装时触发。这是我的代码。
// in CheckboxFlatList.js (parent)
import React, { useState, useEffect, useRef } from 'react';
import { View, StyleSheet, Dimensions, Text } from 'react-native';
import { FlatList } from 'react-native-gesture-handler';
import CheckBox from "./Checkbox";
function CheckboxFlatList(props) {
const [state, setState] = useState([]);
useEffect(() => {
console.log(`listState:`, state);
},[state]);
// setInterval(() => {
// console.log(`listState:`, state);
// },3000 );
return (
<View>
<FlatList
data={data}
keyExtractor={item => item.id.toString()}
renderItem={({ item }) => (
<View>
<View>
<CheckBox id={item.id.toString()} listState={state} stateMerge={setState} isChecked={state.some(x => x === item.id.toString())} />
<Text>{item.name}</Text>
</View>
</View>
)}
/>
</View >
);
}
// in Checkbox.js (child)
import React, { useState, useEffect, useRef, memo } from 'react';
import { CheckBox } from 'react-native-elements';
export default memo(
function Checkbox(props) {
let { listState, stateMerge, isChecked, id } = props;
const [toggleCheckBox, setToggleCheckBox] = useState(isChecked);
const mounted = useRef();
useEffect(() => {
if (!mounted.current) { // do componentDidMount logic
mounted.current = true;
} else { // do componentDidUpdate logic
if (toggleCheckBox) {
if (!listState.some(x => x === id)) { //to avoid a duplication bug
listState.push(id);
}
} else {
while (listState.some(x => x === id)) { //to avoid a duplication bug
let index = listState.indexOf(id);
if (index !== -1) listState.splice(index, 1);
}
}
stateMerge(listState);
}
});
return (
<CheckBox checked={toggleCheckBox} size={40} onPress={() => {
setToggleCheckBox(!toggleCheckBox);
}} />
);
});
非常感谢您的帮助!
答案 0 :(得分:1)
可接受的答案是一个创可贴解决方案,并引入了另一个错误:如果对该状态执行无操作更新,则会触发效果。
由于dep的引用身份未更改,因此未触发 services.AddTransient<IRestClient, RestClient>();
services.AddSingleton<IClient, Client>();
回调。通过重新定义对象来强制使用新的参照身份仅能解决该症状。通常,您应该着眼于根本原因。
在您的情况下,引用身份未更改是违反React状态假设的征兆。应该始终使用适当的setter函数/方法来完成状态更改,而不要通过更改来完成。
以下代码段中令人反感的代码会改变React状态。
useEffect
我们可以通过消除突变来解决它。当我们在不使用突变的情况下编写代码时,身份自然只会在值更改时发生更改。
if (toggleCheckBox) {
if (!listState.some(x => x === id)) { //to avoid a duplication bug
listState.push(id);
}
} else {
while (listState.some(x => x === id)) { //to avoid a duplication bug
let index = listState.indexOf(id);
if (index !== -1) listState.splice(index, 1);
}
}
stateMerge(listState);
状态更改时,您应该会看到 stateMerge(listState =>
if (toggleCheckBox) {
if (!listState.some(x => x === id)) { //to avoid a duplication bug
return [...listState, id];
} else {
return listState;
}
} else {
return listState.filter(x => x !== id);
}
);
被触发,而状态未更改时则不触发。
答案 1 :(得分:0)
在Checkbox.js中调用stateMerge / setState回调的位置
像这样将listState传递给stateMerge
stateMerge([...listState])
将正确触发useEffect