首页 > 解决方案 > 当我使用 history.goBack() 时,我无法从查询中触发 useEffect

问题描述

我正在学习 react 和 materialUI,以及我正在构建的应用程序关于在 amdb api 中搜索并带来一些数据。

在我的“搜索组件”中,我将其设置为当用户自动编写某些内容时,它会自动写入查询并使用此查询触发 useEffect。

第一次搜索效果很好,我列出了所有结果,你可以继续看你想要的电影。这将你带到其他组件,renderMovie,它有一个上一页的按钮(我使用 history.goBack() 设置它)

当我回去时出现问题;我确实回到了搜索组件,但我丢失了之前所做的搜索。我在 url 上有查询,但我无法触发 useEffect。

我尝试更改效果中的依赖项,但似乎没有任何效果。我也尝试过使用useMemo,但我无法让它工作,因为我本身没有函数(我的意思是我唯一的函数是handleInputChange)。

你能给点建议吗?我怎么能做到?我可以使用什么方法?或者你能给我其他的想法来尝试吗?

提前致谢!

这是我的 seachComponent,如果您有任何问题...


    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: {
            '& > *': {
                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}&language=es-ES&query=${s}&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 && <p className={classes.noResults}>No hay resultados para mostrar</p>
                        }
                    </Grid>
                </Container>
    
                {
                    (showPagination && pageTotal > 1 && !showNoResult ) && 
                        (
                            <PaginationComp pageTotal={pageTotal} setPage={setPage} page={page} />
                        )
                }
            </>
        );
    }

这是我的 renderMovie 的按钮


    <Button 
        variant="contained" 
        color="primary"  
        href="#contained-buttons"
        size="large"
        component="div"
        onClick={() => history.goBack()}
    >
                                Volver
                            </Button>

标签: reactjssearchbrowser-history

解决方案


当导航离开时,您的 searchComponent 页面被卸载,并将history.goBack()重新安装您的页面组件,因此与渲染新页面相同。

对于解决方案,您可能需要在用户输入时更新同步 url-query 参数,例如当用户输入时action您将 url 更新为喜欢/movie/search?q=action

或者,您可以将用户搜索保留在 localStorage 左右,并在用户进入搜索页面时读取该值。


推荐阅读