En el componente funcional de mi aplicación, defino una función que debe llamarse una vez que el usuario hace clic en el botón de búsqueda en el componente funcional de mi MainHeader .
function App(props) { const location = useLocation(); const [movies, setMovies] = useState(DUMMY_MOVIES); const filterMovies = () => { console.log(location.search); } return ( <MainHeader onFilterMovies={filterMovies}> <Switch> <Route path="/" exact> <Redirect to="/movies" /> </Route> <Route path="/movies" exact> <Movies movies={movies} /> </Route> <Route path="/movies/:movieId"> <MovieDetails /> </Route> </Switch> </MainHeader> ); } En el componente MainHeader hay un controlador de envío que se ejecutará una vez que el usuario haga clic en el botón de búsqueda, y allí (SubmitHandler) agrego searchTerm como clave y searchTermValue como el valor del parámetro de consulta y reemplazo la página con location.replace(`/movies?searchTerm=${searchTermValue}`) . ¡Y finalmente llamo a OnFitlerMovies que recibo de los props para informar al componente de la App que hemos terminado!
En el componente funcional de la App donde defino la función FiltrerMovies , simplemente registro el valor del parámetro de consulta en la consola.
Pero la bruja de valor que recibo es el valor anterior del parámetro de consulta. Me refiero a que cuando ingreso something en la entrada de búsqueda y luego hago clic en el botón Buscar, lo recibo en el método FilterMovies como una cadena vacía, pero la próxima vez, incluso si no ingreso nada (me refiero a una cadena vacía), el valor correcto para ¡La hora anterior se registra!
const MainHeader = (props) => { const history = useHistory(); const searchTermInputRef = useRef(); const submitHandler = (e) => { e.preventDefault(); const searchTermValue = searchTermInputRef.current.value.trim(); history.replace(`/movies?searchTerm=${searchTermValue}`); props.onFilterMovies(); }; ... Supongo que no podemos usar ganchos ReactRouterDomV5 dentro de un componente que no está en el componente Route .
Ahora, ¿cómo puedo resolver este problema?
La devolución de llamada de filterMovies tiene un cierre obsoleto sobre el valor de location.search , por lo que verá el valor obsoleto.
Use un useEffect para registrar el valor actualizado de location.search .
Ejemplo:
useEffect(() => { console.log(location.search); }, [location.search]); Si desea utilizar el parámetro querySearch para filtrar el estado de las movies antes de pasarlo al componente Movies , hágalo en línea.
Ejemplo:
function App() { const location = useLocation(); const [movies, setMovies] = useState(DUMMY_MOVIES); const searchParams = new URLSearchParams(location.search); const searchTerm = searchPararms.get("searchTerm"); useEffect(() => { console.log(location.search); }, [location.search]); return ( <MainHeader> <Switch> <Route path="/" exact> <Redirect to="/movies" /> </Route> <Route path="/movies" exact> <Movies movies={movies.filter(movie => { if (searchTerm) { return movie.name.toLowerCase().includes(searchTerm.toLowerCase()); } return true; })} /> </Route> <Route path="/movies/:movieId"> <MovieDetails /> </Route> </Switch> </MainHeader> ); } Si desea mejorar el rendimiento, utilice el gancho useMemo para memorizar el valor de las películas filtradas.
Ejemplo:
const location = useLocation(); const [movies, setMovies] = useState(DUMMY_MOVIES); const searchParams = new URLSearchParams(location.search); const searchTerm = searchPararms.get("searchTerm"); const filteredMovies = useMemo(() => { return movies.filter(movie => { if (searchTerm) { return movie.name.toLowerCase().includes(searchTerm.toLowerCase()); } return true; } }, [movies, searchTerm]); ... <Route path="/movies" exact> <Movies movies={filteredMovies} /> </Route>