Starfs
Starfs

Reputation: 488

React Native pass a function as props to child component

I am trying to pass a function from one component to its child, in this case Posts.js maps through each post and adds a prop called changeState. But It does not appear to be working.

The code for Posts.js

import Post from "./post"

export default function posts() {

  const posts = [<arrayOfPosts>];

  const [favoritesChanged, setFavoritesChanged] = useState(1);

  const changeState = () => {
    setFavoritesChanged(Math.random());
  }

  useEffect(() => {
    console.log("favorites changed");
  }, [favoritesChanged])

  return (
    {posts.map((post) => {
      <Post changeState={changeState} key={post.id} />
    }
  )
}

Then in the post.js file we have:

const Post = ({ changeState }) => {
  console.log("change state: ", changeState);
  return (
    <View>
      <TouchableOpacity onPress={changeState}>
        <Text>Click here to test.</Text>
      </TouchableOpacity>
      <Text>{post.title}</Text>
    </View>
  )
}

export default Post

But the press action doesn't fire the changeState function and where it is being console.logged it says undefined. Why is this not working?

Upvotes: 3

Views: 1923

Answers (2)

Hritik Sharma
Hritik Sharma

Reputation: 2010

Try using this as the return in the posts component:

return (
    <>
    {
      posts.map(val => <Post changeState={changeState} key={val}/>)
    }
    </>
)

See this as a reference : Sandbox reference

Upvotes: 0

Drew Reese
Drew Reese

Reputation: 202667

You are missing returning the Post component JSX in the .map callback:

return (
  {posts.map((post) => {
    return <Post changeState={changeState} key={post.id} post={post} />
  })}
);

or using an implicit arrow function return:

return (
  {posts.map((post) => (
    <Post changeState={changeState} key={post.id} post={post} />
  ))}
);

Ensure you are destructuring all the props you need that are passed:

const Post = ({ changeState, post }) => {
  return (
    <View>
      <TouchableOpacity onPress={changeState}>
        <Text>Click here to test.</Text>
      </TouchableOpacity>
      <Text>{post.title}</Text>
    </View>
  )
};

Upvotes: 1

Related Questions