React Native-子の状態が変更されました。親を更新する方法は?

Nov 25 2020

現在、子コンポーネントの状態を変更していますが、親を更新したいと思います。最初は、親から子にデータを渡し、次に子で状態を変更します。これを行うと、親がまだ更新されていないためアプリで何も起こりませんが、アプリをリロードすると、加えられた変更が更新されます。

また、反応ナビゲーションを使用して、親画面から子画面に移動しています。

これが私のコードです:

親画面:

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

子画面:

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>

)}

親コンポーネントの投稿がisLikedでlikesCountの場合、どうすれば更新できますか?

また、私はReduxを使用していません。

更新

次のことを試しましたが、それでもエラーが発生し続けます。

親画面:

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

子画面:

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

回答

1 LeslieAlldridge Nov 25 2020 at 08:53

Reduxなどの何らかの形式の共有状態を使用せずに、目的の結果を達成するための最良の方法は、コンポーネントの構造を決定することです。

次のような構造になっているようです。

親(知らないlikes)->子(知っているlikes

しかし、あなたはこのようなものを望んでいます:

親(知っているlikes)->子(との相互作用likes

したがって、私はあなたを持つお勧めstateの親コンポーネントキープトラックにisLikedlikesCount。親は、メソッドハンドラーをaddToLikes(post.id,user.id)。などの子コンポーネントにも渡します。

コード例:

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;