#javascript #html #reactjs
Вопрос:
Я перестраиваю статический веб — сайт в react https://movie-list-website-wt.netlify.app/ Я пытаюсь передать функцию поиска для реагирования. Моя текущая функция поиска работает по назначению, она возвращает массив фильмов, в которых выполняется поиск, я хочу, чтобы она обновила данные, полученные с помощью карточек фильмов, чтобы при поиске по запросу карточки фильмов использовали возвращенные данные поиска вместо исходных. Это мой App.js файл
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.descamp;' 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 amp;amp;
movies.map((movie) => (
<Movies key={movie.id} {...movie} />))}
</div>
<Routes>
<Route exact path='/' />
</Routes>
</Router>
</>
);
}
export default App;
и это часть моего главного навигационного компонента, который включает в себя панель поиска и функцию
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 `amp;language=en-USamp;page=1amp;include_adult=falseamp;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>
Ответ №1:
Если вам нужно отфильтровать movies
массив в Topnav
компоненте, вы можете просто передать компоненту setMovies
функцию состояния как prop.
Все, что вам нужно сделать, это обновить данные в onChange
методе:
App.js
return (
<>
<Router>
<!-- Pass the prop to the component -->
<Topnav setMovies={setMovies}/>
<div className="movie-container">
{movies.length > 0 amp;amp;
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 `amp;language=en-USamp;page=1amp;include_adult=falseamp;query=${e.target.value}`)
.then((res) => res.json())
.then((data) => {
console.log(data.results);
// Update the data once fetched
setMovies(data.results)
})
}
...
Комментарии:
1. Это сработало как заклинание, большое вам спасибо, реагировать-это довольно сложная задача для меня, прыгнуть в нее
Ответ №2:
Это прямолинейно, просто переместите метод onChange в родительский компонент и передайте его в качестве реквизита
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.descamp;' 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 ([]);
const [, setQuery] = useState("")
useEffect(() => {
fetch (API_URL)
.then(res => res.json())
.then(data => {
console.log(data);
setMovies(data.results);
});
}, [])
const onChange = (e) => {
e.preventDefault();
setQuery(e.target.value)
fetch(searchURL `amp;language=en-USamp;page=1amp;include_adult=falseamp;query=${e.target.value}`)
.then((res) => res.json())
.then((data) => {
console.log(data.results);
// DO what ever you want with the move array
})
}
return (
<>
<Router>
<Topnav onChange={onChange} query={query}/>
<div className="movie-container">
{movies.length > 0 amp;amp;
movies.map((movie) => (
<Movies key={movie.id} {...movie} />))}
</div>
<Routes>
<Route exact path='/' />
</Routes>
</Router>
</>
);
}
таким образом, вы можете редактировать массив фильмов в компоненте ПРИЛОЖЕНИЯ,
тогда ваш дочерний компонент будет выглядеть примерно так
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import './Topnav.css';
import { searchURL } from '../App';
function Topnav({onChange, query}) {
const [click, setClick] = useState(false)
const handleClick = () => setClick(!click)
const modeToggle = () => {
document.body.classList.toggle('dark')
}
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>
...