我是本机反应的新手,我的 JS 有点生疏。我需要能够更改 Firestore 收藏的价值。我有两个按钮可以通过设置状态来改变 typeOfPost 的值。 Component1 可以成功获取“this.state.typeOfPost”。但是,当我单击其中一个按钮并更新状态时,不会调用异步函数内的日志。它仅在应用程序最初呈现时调用。我觉得奇怪的是,我在 Component1 顶部的日志会按预期显示。有没有更好的方法来做到这一点?
class Forum extends Component {
state = {
typeOfPost: ' '
}
onPressSitter = () => {
this.setState({
typeOfPost: 'sitterPosts'
})
}
onPressNeedSitter = () => {
this.setState({
typeOfPost: 'needPosts'
})
}
render() {
return (
<View style={styles.container}>
<View style={styles.row}>
<TouchableOpacity
style={styles.button}
onPress={this.onPressSitter}
>
<Text>I am a sitter</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={this.onPressNeedSitter}
>
<Text>Need a sitter</Text>
</TouchableOpacity>
</View>
<View>
<Component1 typeOfPost = {this.state.typeOfPost}> </Component1>
</View>
</View>
)
}
}
const Component1 = (props) => {
console.log("type of post " + props.typeOfPost);
const [loading, setLoading] = useState(true); // Set loading to true on component mount
const [data, setData] = useState([]); // Initial empty array of data
const getData = async () => {
console.log("type of post inside async " + props.typeOfPost);
const subscriber = firestore()
.collection(props.typeOfPost) // need to be able to update this
.onSnapshot(querySnapshot => {
const data = [];
querySnapshot.forEach(documentSnapshot => {
data.push({
...documentSnapshot.data(),
key: documentSnapshot.id,
});
});
setData(data);
setLoading(false);
});
// Unsubscribe from events when no longer in use
return () => subscriber();
}
useEffect(() => {
getData();
}, [])
if (loading) {
return <ActivityIndicator />;
}
return (
<FlatList
data={data}
ListEmptyComponent={
<View style={styles.flatListEmpty}>
<Text style={{ fontWeight: 'bold' }}>No Data</Text>
</View>
}
renderItem={({ item }) => (
<View>
<Text>User ID: {item.fullName}</Text>
</View>
)}
/>
)
}
答案 0 :(得分:1)
mount
和 render
之间存在差异。除了我所做的一些评论外,我认为您的代码没有问题。问题是,当您更改 typeOfPost
时,会重新渲染组件,但不会再次调用 useEffect,因为您说的是,它只是在第一次挂载时才调用:
useEffect(() => {
}, []) // ---> [] says to run only when first mounted
但是在这里,您希望它在 typeOfPost
更改时运行。因此,您可以这样做:
useEffect(() => {
getData();
}, [typeofPost])
class Forum extends Component {
state = {
typeOfPost: ' '
}
onPressSitter = () => {
this.setState({
typeOfPost: 'sitterPosts'
})
}
onPressNeedSitter = () => {
this.setState({
typeOfPost: 'needPosts'
})
}
render() {
return (
<View style={styles.container}>
<View style={styles.row}>
<TouchableOpacity
style={styles.button}
onPress={this.onPressSitter}
>
<Text>I am a sitter</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={this.onPressNeedSitter}
>
<Text>Need a sitter</Text>
</TouchableOpacity>
</View>
<View>
<Component1 typeOfPost = {this.state.typeOfPost}> </Component1>
</View>
</View>
)
}
}
const Component1 = (props) => {
const { typeOfPost } = props
console.log("type of post " + props.typeOfPost);
const [loading, setLoading] = useState(true); // Set loading to true on component mount
const [data, setData] = useState([]); // Initial empty array of data
const getData = () => {
setLoading(true)
console.log("type of post inside async " + props.typeOfPost);
const subscriber = firestore()
.collection(props.typeOfPost) // need to be able to update this
.onSnapshot(querySnapshot => {
const data = [];
querySnapshot.forEach(documentSnapshot => {
data.push({
...documentSnapshot.data(),
key: documentSnapshot.id,
});
});
setData(data);
setLoading(false);
});
// Unsubscribe from events when no longer in use
return () => subscriber();
}
useEffect(() => {
getData();
}, [typeofPost])
if (loading) {
return <ActivityIndicator />;
}
return (
<FlatList
data={data}
ListEmptyComponent={
<View style={styles.flatListEmpty}>
<Text style={{ fontWeight: 'bold' }}>No Data</Text>
</View>
}
renderItem={({ item }) => (
<View>
<Text>User ID: {item.fullName}</Text>
</View>
)}
/>
)
}
答案 1 :(得分:0)
const ButtonPressed = useCallback(() => {
setLoading(true);
getData()
}).then(() => setLoading(false));
}, [loading]);