React Native - State cambió en child, ¿cómo actualizar Parent?

Nov 25 2020

Actualmente estoy cambiando el estado en mi componente secundario y ahora quiero actualizar a mi padre. Inicialmente, estoy pasando datos del padre al niño y luego en el niño estoy cambiando el estado. cuando hago eso, no sucede nada en la aplicación porque el padre todavía no está actualizado, pero cuando vuelvo a cargar la aplicación, se actualizan los cambios que se realizaron.

También estoy usando la navegación de reacción para pasar de la pantalla principal a la pantalla secundaria.

Aquí está mi código:

Pantalla de padres:

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)}
        />
      )}
    />
  );
  }

Pantalla infantil:

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>

)}

¿Cómo actualizo si una publicación tiene Me gusta y cuenta Me gusta en el componente principal?

Además, no estoy usando Redux.

Actualización :

Intenté hacer lo siguiente pero sigo recibiendo un error.

Pantalla de padres:

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>
  );
}

Pantalla infantil:

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>
  );
}

Respuestas

1 LeslieAlldridge Nov 25 2020 at 08:53

Sin usar alguna forma de estado compartido como Redux, la mejor manera de lograr el resultado que busca es decidir la estructura de su componente.

Parece que tienes una estructura como esta:

Padre (no sabe sobre likes) -> Niño (sabe sobre likes)

Pero quieres algo como esto:

Padre (conoce likes) -> Niño (interacción con likes)

Por lo tanto, recomiendo tener stateen el componente principal un seguimiento de isLikedy likesCount. El padre también pasará un controlador de método al componente hijo, como addToLikes(post.id,user.id).

Código de ejemplo:

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;