In My App Functional Component I Define a Function That Should be Call Once The User Clicked On The Search Button In My MainHeader
Functional Component.
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>
);
}
In The MainHeader
Component There Is A Submit Handler That Will Execute Once The User Click the Search Button, And In There(SubmitHandler) I Append searchTerm
As A Key And searchTermValue
As The Value Of The Query Parameter And Replace The Page With location.replace(`/movies?searchTerm=${searchTermValue}`)
.
And Finally I Call The OnFitlerMovies Whitch I Receive From props
To Inform The App
Component That We're DONE!
In App
Functional Component Where I Define The FiltrerMovies
Function, I Simply Log The Query Parameter Value To The Console.
But The Value Witch I Receive Is The Previous Value Of The Query Parameter.
I Mean When I Enter something
In The Search Input And Then Click The Search Button I Receive It In FilterMovies
Method As An Empty String, But The Next Time, Even If I Dont Enter Anything(I Mean A Empty String), The Correct Value For The Previous Time Get Logged!
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();
};
...
My Guess Is That We Can't Use ReactRouterDomV5 Hooks Inside of A Component Witch Is Not In Route
Component.
Now How Can I Solve This Problem?
CodePudding user response:
Issue
The filterMovies
callback has a stale closure over the location.search
value, so you see the stale value.
Solution
Use a useEffect
hook to log the updated location.search
value.
Example:
useEffect(() => {
console.log(location.search);
}, [location.search]);
If you are wanting to use the querySearch param to filter the movies
state prior to passing it to the Movies
component do this inline.
Example:
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 /* searchTerm condition to filter by */
}
return true;
})}
/>
</Route>
<Route path="/movies/:movieId">
<MovieDetails />
</Route>
</Switch>
</MainHeader>
);
}
If you want to improve performance then use the useMemo
hook to memoize the filtered movies value.
Example:
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 /* searchTerm condition to filter by */
}
return true;
}
}, [movies, searchTerm]);
...
<Route path="/movies" exact>
<Movies movies={filteredMovies} />
</Route>