React updating anothers components data

Viewed 36

I'm trying to update another component's data depending on which item I click from the list component.

I have a list of "Movies" (Just movie Title). When I click on a movie title from the list, I want another component to show its info (title and description)

Overview of the application

Page Component

export default ({ movies }) => {
  return (
    <div id="home">
      <div className="movies">
        <List movies={movies}/>
      </div>
      <div className="">
        <Info movies={movies}/>
      </div>
    </div>
  );
}

List Component

export default ({ movies }) => {
  return (
    <ul>
      {movies.map((movie, index) =>
        <li key={index}>
          {movie.title}
        </li>
      )}
    </ul>
  );
}

Info Component

export default ({ movies }) => {
  return (
    <div className="movie">
      <h2>{movies.title}</h2>     //Active movie title
      <p>{movies.description}</p> //Active movie description
    </div>
  );
}
2 Answers

An easy way to achieve this would be to handle movies inside the Page Component or into a WrapperComponent.

PageComponent

export default () => {
  const [movies, setMovies] = useState([
    { title: "Movie Title 1", id: 1, active: false },
    { title: "Movie Title 2", id: 2, active: false },
    { title: "Movie Title 3", id: 3, active: false },
  ]);

  const onMovieClick = useCallback(
    (movie) => {
      setMovies(
        movies.map(({ id, ...other }) =>
          id === movie.id
            ? { ...other, id, active: true }
            : { ...other, id, active: false }
        )
      );
    },
    [movies, setMovies]
  );

  const selectedMovie = movies.filter(({ active }) => !!active);

  return (
    <div>
      <ListComponent movies={movies} onMovieClick={onMovieClick} />
      {selectedMovie.length ? (
        <InfoComponent movie={selectedMovie[0]} />
      ) : (
        "No movie selected"
      )}
    </div>
  );
};

and handle the onMovieClick inside the ListComponent

export default ({ movies, onMovieClick }) => {
  return (
    <ul>
      {movies.map((movie, index) =>
        <li key={index} onClick={() => onMovieClick(movie)}>
          {movie.title}
        </li>
      )}
    </ul>
  );
}

Info Component

export default ({ movie }) => {
  // single movie
  return (
    <div className="movie">
      <h2>{movie.title}</h2>     
      <p>{movie.description}</p>
    </div>
  );
}

This might help

// List Component
export default ({ movies }) => {
  // set default selected state    
  const [selectedMovie, setSelectedMovie] = useState(null); 

  const handleClick = (movie) => {
     setSelectedMovie(movie); // set state here when select movie
  }

  return (
   <View>
     <ul>
      {movies.map((movie, index) =>
        <li key={index} onClick={() => handleClick(movie)}>
          {movie.title}
        </li>
      )}
     </ul>
     // render info comp if movie selected    
     { selectedMovie ? <InfoComponen movie={selectedMovie} /> : null } 
   </View>
  );
}


// Info Componen
export default ({ movie }) => {
  return (
    ........
  );
}
Related