React Native - Stan zmieniony w dziecku, jak zaktualizować Parent?
obecnie zmieniam stan w moim komponencie podrzędnym, a teraz chcę zaktualizować mojego rodzica. Początkowo przekazuję dane od rodzica dziecku, następnie w dziecku zmieniam stan. kiedy to robię, nic się nie dzieje w aplikacji, ponieważ rodzic nadal nie jest aktualizowany, ale kiedy ponownie ładuję aplikację, wprowadzone zmiany są aktualizowane.
Używam również nawigacji reagowania, aby przejść z ekranu rodzica do ekranu dziecka.
Oto mój kod:
Ekran nadrzędny:
function PostsScreen({navigation}) {
const [posts, setPosts] = useState([]);
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
const loadPosts = async () => {
setLoading(true);
const response = await postsApi.getPosts();
setLoading(false);
if (!response.ok) return setError(true);
setError(false);
setPosts(response.data);
};
useEffect(() => {
loadPosts();
}, []);
return(
<ActivityIndicator visible={loading} />
<FlatList
data={posts}
keyExtractor={(post) => post.id.toString()}
renderItem={({ item }) => (
<Card
title={item.title}
subTitle={item.subTitle}
onPress={() =>
navigation.navigate(routes.POST_DETAILS,item)}
/>
)}
/>
);
}
Ekran podrzędny:
function PostDetailsScreen({ route }) {
const post = route.params;
const { user} = useAuth();
const [addedToLikes, setAddedToLikes] = useState(post.isLiked);
const[likesCount,setLikesCount]=useState(post.likesCount)
const addToLikes = (PostId,userId) => {
postsApi.likePost({PostId,userId});
setAddedToLikes(!addedToLikes);
};
let show_likes="";
if(addedToLikes){
show_likes=(likesCount >1)?(("Liked by you")+" and "+(likesCount - 1)+((likesCount ==2)?( "
other"):(" others"))):("Liked by you");
}else if(likesCount >0){
show_likes=(likesCount ==1)?(likesCount+ " like"):(likesCount + " likes");
}
return(
<TouchableOpacity onPress={() => {addToLikes(post.id,user.id)}}>
{addedToLikes?<MaterialCommunityIcons
name="heart"
/>:<MaterialCommunityIcons
name="heart-outline"
/>}
</TouchableOpacity>
<View><TextInput>{show_likes}</TextInput></View>
)}
Jak zaktualizować, jeśli post jestLiked i LikeCount w komponencie nadrzędnym?
Nie używam też Redux.
Aktualizacja :
Próbowałem wykonać następujące czynności, ale nadal pojawia się błąd.
Ekran nadrzędny:
function PostsScreen({ navigation }) {
const [posts, setPosts] = useState([]);
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
const loadPosts = async () => {
setLoading(true);
const response = await postsApi.getPosts();
setLoading(false);
if (!response.ok) return setError(true);
setError(false);
setPosts(response.data);
};
useEffect(() => {
loadPosts();
}, []);
const [addedToLikes, setAddedToLikes] = useState(post.isLiked);
const addToLikes = (PostId, userId) => {
postsApi.likePost({ PostId, userId });
setAddedToLikes(!addedToLikes);
};
const { user } = useAuth();
return (
<React.Fragment>
<ActivityIndicator visible={loading} />
<FlatList
data={posts}
keyExtractor={post => post.id.toString()}
renderItem={({ item }) => (
<Card
title={item.title}
subTitle={item.subTitle}
onPress={() => navigation.navigate(routes.POST_DETAILS, item)}
/>
)}
/>
<PostDetailsScreen addToLikes={addToLikes(posts.id, user.id)} />
</React.Fragment>
);
}
Ekran podrzędny:
function PostDetailsScreen({ route, addedToLikes, addToLikes }) {
const post = route.params;
const [likesCount, setLikesCount] = useState(post.likesCount);
let show_likes = "";
if (addedToLikes) {
show_likes =
likesCount > 1
? "Liked by you" + " and " + (likesCount - 1) + (likesCount == 2 ? " other" : " others")
: "Liked by you";
} else if (likesCount > 0) {
show_likes = likesCount == 1 ? likesCount + " like" : likesCount + " likes";
}
return (
<React.Fragment>
<TouchableOpacity
onPress={() => {
addToLikes;
}}
>
{addedToLikes ? <MaterialCommunityIcons name="heart" /> : <MaterialCommunityIcons name="heart-outline" />}
</TouchableOpacity>
<View>
<TextInput>{show_likes}</TextInput>
</View>
</React.Fragment>
);
}
Odpowiedzi
Bez korzystania z jakiejś formy współdzielonego stanu, takiej jak Redux, najlepszym sposobem osiągnięcia pożądanego wyniku jest podjęcie decyzji o strukturze komponentów.
Wygląda na to, że masz taką strukturę:
Rodzic (nie wie o likes
) -> Dziecko (wie o likes
)
Ale chcesz czegoś takiego:
Rodzic (wie o likes
) -> Dziecko (interakcja z likes
)
Dlatego zalecam, aby Twój state
komponent nadrzędny śledził isLiked
i likesCount
. Rodzic przekaże również procedurę obsługi metody do składnika potomnego, takiego jak addToLikes(post.id,user.id)
.
Przykładowy kod:
import React from 'react';
class Parent extends React.Component{
constructor(props){
super(props);
this.state = {
data: null
}
}
handleCallback = (childData) =>{
this.setState({data: childData})
}
render(){
const {data} = this.state;
return(
<div>
<Child parentCallback = {this.handleCallback}/>
{data}
</div>
)
}
}
class Child extends React.Component{
onTrigger = (event) => {
this.props.parentCallback("Data from child");
event.preventDefault();
}
render(){
return(
<div>
<form onSubmit = {this.onTrigger}>
<input type = "submit" value = "Submit"/>
</form>
</div>
)
}
}
export default Parent;