Skip to content
Advertisement

How to update array of a component from another component’s function?

I am rebuilding a static website in react https://movie-list-website-wt.netlify.app/ I am trying to transfer the search function to react. My current search function works as intended, it returns an array of movies that is being searched, I want it to update the data fetched by the movie cards so that when I search a query, the movie cards use the returned search data instead of the original one this is my App.js file

import React, { useEffect, useState } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Movies from './components/Movies';
import Topnav from './components/Topnav';
import './App.css';
import './components/Movies.css';

export const API_KEY = 'api_key=247b6aa143f3f2c0b100c0cbdfb1ac99';
export const BASE_URL = 'https://api.themoviedb.org/3';
export const API_URL = BASE_URL + '/discover/movie?sort_by=popularity.desc&' + API_KEY;
export const IMG_URL = 'https://image.tmdb.org/t/p/w500';
export const searchURL = BASE_URL + '/search/movie?'+ API_KEY;

function App() {
  const [movies, setMovies] = useState ([]);

  useEffect(() => {
    fetch (API_URL)
      .then(res => res.json())
      .then(data => {
        console.log(data);
        setMovies(data.results);
      });
  }, [])

  return (
    <>
        <Router>
          <Topnav />
          <div className="movie-container">
            {movies.length > 0 && 
              movies.map((movie) => (
                <Movies key={movie.id} {...movie} />))}
          </div>
          <Routes>
            <Route exact path='/' />
          </Routes>
        </Router>
    </>
  );
}

export default App;

and this is part of my Top navigation component that includes the search bar and function

import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import './Topnav.css';
import { searchURL } from '../App';

function Topnav() {
    const [click, setClick] = useState(false)
    const handleClick = () => setClick(!click)

    const modeToggle = () => {
        document.body.classList.toggle('dark')
    }

    const [query, setQuery] = useState("")

    const onChange = (e) => {
        e.preventDefault();
        setQuery(e.target.value)
        fetch(searchURL+`&language=en-US&page=1&include_adult=false&query=${e.target.value}`)
        .then((res) => res.json())
        .then((data) => {
            console.log(data.results);
        })
    }

    return (
        <>
        <nav className="topnav">
            <div className="topnav-container">
                <Link to='/' className='topnav-logo'>
                    <img src={require('../img/logo.png').default} alt="logo" />
                </Link>
                <div className="wrapper">
                    <form id='search-bar'>
                        <input
                        type="text"
                        placeholder="Search"
                        className="search"
                        id="search"
                        value={query}
                        onChange={onChange}
                        />
                    </form>
                    <label className="switch">
                        <input type="checkbox" id="mode-toggle" onChange={modeToggle}/>
                    </label>
                </div>

Advertisement

Answer

If you need to filter the movies array in the Topnav component you can just pass the setMovies state function as prop to the component.
All you need to do is update the data in the onChange method:

App.js

  return (
    <>
        <Router>
          <!-- Pass the prop to the component -->
          <Topnav setMovies={setMovies}/>
          <div className="movie-container">
            {movies.length > 0 && 
              movies.map((movie) => (
                <Movies key={movie.id} {...movie} />))}
          </div>
          <Routes>
            <Route exact path='/' />
          </Routes>
        </Router>
    </>
  );

Topnav.js

function Topnav({ setMovies }) {

    ...

    const onChange = (e) => {
        e.preventDefault();
        setQuery(e.target.value)
        fetch(searchURL+`&language=en-US&page=1&include_adult=false&query=${e.target.value}`)
        .then((res) => res.json())
        .then((data) => {
            console.log(data.results);
            // Update the data once fetched
            setMovies(data.results)
        })
    }

    ...
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement