#reactjs #search #browser-history
Вопрос:
Я изучаю react и MaterialUI, и приложение, которое я создаю, посвящено поиску в api amdb и предоставлению некоторых данных.
В моем «компоненте поиска» я настроил его так, что, когда пользователь что-то автоматически пишет, он записывает запрос и запускает эффект использования с этим запросом.
Первый поиск работает идеально, я перечисляю все результаты, и вы можете перейти к нужному вам фильму. Это приведет вас к другому компоненту, renderMovie, и у него есть кнопка на предыдущую страницу (я настроил ее с помощью history.GoBack() )
Проблема появляется, когда я возвращаюсь; Я возвращаюсь к компоненту поиска, но я теряю поиск, который выполнял перед входом. У меня есть запрос по URL-адресу, но я не могу запустить эффект использования.
Я попытался изменить зависимости в эффекте, но, похоже, ничего не работает. Я тоже пытался использовать useMemo, но я не могу заставить его работать, потому что у меня нет самой функции (я имею в виду, что единственная функция, которая у меня есть, — это handleInputChange).
Не могли бы вы дать несколько советов? Как я мог это сделать? Какой подход я мог бы использовать? Или, может быть, вы могли бы дать мне другие идеи, чтобы попробовать?
Заранее спасибо!
Это мой личный компонент, если у вас есть какие-то вопросы…
import React, { useEffect, useState } from 'react';
import { useHistory, useLocation } from "react-router-dom";
import { makeStyles } from '@material-ui/core/styles';
import TextField from '@material-ui/core/TextField';
import { Container, Grid } from '@material-ui/core';
import queryString from "query-string";
import MovieCardItem from '../components/MovieCardItem';
import PaginationComp from '../components/PaginationComp';
import { ReactComponent as Logo } from "../assets/Search.svg";
import { API_KEY, URL_API } from '../utils/constants';
const useStyles = makeStyles((theme) => ({
root: {
'amp; > *': {
margin: theme.spacing(1),
width: '25ch',
},
},
bigContainer: {
margin: '1rem auto 3rem auto',
textAlign: 'center',
justifyContent: 'center',
},
media: {
width: '100%',
height: '100%',
margin: '1rem auto',
},
textField:{
width: '100%'
},
noResults: {
margin: '0 auto',
}
}));
export default function SearchPage() {
const classes = useStyles();
const history = useHistory();
const location = useLocation();
const [firstRender, setFirstRender] = useState(true);
const [movieList, setMovieList] = useState([]);
const [showMovieList, setShowMovieList] = useState(false);
const [showNoResult, setShowNoResult] = useState(false)
const [page, setPage] = useState(1);
const [pageTotal, setPageTotal] = useState(1);
const [showPagination, setShowPagination] = useState(false);
const handleInputChange = (e) => {
setFirstRender(false);
if (e.target.value === ' ') {
e.target.value = '';
return null
}
const urlParams = queryString.parse(location.search);
urlParams.s = e.target.value;
if(e.target.value === '') {
setShowPagination(false);
setFirstRender(true)
history.push(`/buscar`)
setShowMovieList(false);
} else {
history.push(`?${queryString.stringify(urlParams)}`);
setShowMovieList(true);
setShowPagination(true);
}
}
useEffect(() => {
if (firstRender) return null;
const getSearch = async () => {
const searchValue = queryString.parseUrl(location.search);
const { s } = searchValue.query;
if(s === undefined) return null;
const response = await fetch(`${URL_API}/search/movie?api_key=${API_KEY}amp;language=es-ESamp;query=${s}amp;page=${page}` );
const movies = await response.json();
// console.log(movies)
if (movies.results.length === 0) {
setShowNoResult(true);
setShowMovieList(false);
} else {
setShowNoResult(false);
setPageTotal(movies.total_pages);
setMovieList(movies.results);
}
}
getSearch();
// eslint-disable-next-line
}, [location.search, page])
return (
<>
<Grid container spacing={0} alignItems="center" className={classes.bigContainer}>
<Grid item xs={5} sm={4} md={3} className={classes.smallContainer} >
<Logo className={classes.media} />
<form
className={classes.root}
noValidate autoComplete="off"
onSubmit={ (e) => e.preventDefault() }
>
<TextField
id="outlined-basic"
label="Buscar pelicula..."
variant="outlined"
className={classes.textField}
onChange={ handleInputChange }
/>
</form>
</Grid>
</Grid>
<Container >
<Grid container spacing={2} alignItems="center">
{
(showMovieList || movieList.length===0 ) ? (
movieList.length === 0 ? null : (
movieList.map( (movie) => (
<Grid item xs={12} sm={6} md={3} key={movie.id} >
<MovieCardItem movie={movie} key={movie.id} />
</Grid>
))
)
) : (null)
}
{
showNoResult amp;amp; <p className={classes.noResults}>No hay resultados para mostrar</p>
}
</Grid>
</Container>
{
(showPagination amp;amp; pageTotal > 1 amp;amp; !showNoResult ) amp;amp;
(
<PaginationComp pageTotal={pageTotal} setPage={setPage} page={page} />
)
}
</>
);
}
А это кнопка моего нового фильма
<Button
variant="contained"
color="primary"
href="#contained-buttons"
size="large"
component="div"
onClick={() => history.goBack()}
>
Volver
</Button>
Комментарии:
1. вся выборка зависит только от местоположения.поиск, включает текущую страницу, разбиение на страницы.страница, текстовое поле.Значение по умолчанию инициализировано из местоположения.поиск, Разбиение на страницы.setPage, текстовое поле. Местоположение триггера onChange.нажмите, чтобы изменить URL-адрес
2. Теоретически, все поиски основаны на URL-адресе и отслеживают изменения в URL-адресе. Все значения инициализации компонентов берутся из URL-адреса, и URL-адрес напрямую изменяется при изменении значения компонента
3. в вашем случае невыполнение работы может привести к
if (firstRender) return null;
удалению этой строки и текстового поля. При обмене отмените изменение местоположения.поиск, кажется, в порядке
Ответ №1:
Когда вы удаляетесь, ваша страница поискового компонента размонтирована, и history.goBack()
ваш компонент страницы будет повторно смонтирован, так что это то же самое, что и рендеринг новой страницы.
Для решения вам может потребоваться обновить параметр URL-запроса синхронизации, в то время как пользователь вводит «нравится», когда пользователь вводит action
«нравится». /movie/search?q=action
В качестве альтернативы вы можете сохранить поиск пользователя в локальном хранилище или около того и прочитать значение, когда пользователь войдет на страницу поиска.