简体   繁体   中英

Handle browser back button with React router dom

this is my first time here

I am working on a website that shows infos about movies and tv shows using TMDB API, React, Redux and React Router Dom. I wanted to sort movies by genres and page. So in my Movies Page, i have a list of genres and each one of them has an ID which make my useEffect() hooks to rerender each time a new genre is clicked or the page is changed.

The link to the movies page looks like this movies/:genreID/:pageNumber . So basically, the idea was each time a genre is clicked or the page is changed, the url updates and i get the new genreID and pageNumber from it using useParams(), then i send them to dispatch and the component rerender.

My code looks like this

 const Movies = ({ isFrench, isOpen }) => { const dispatch = useDispatch(); const history = useHistory(); const { genreID, pageNumber } = useParams(); const language = isFrench? "fr": ""; const [genres, setGenres] = useState(genreID); const [page, setPage] = useState(pageNumber); useEffect(() => { dispatch(fetchMovies(language, page, genres)); history.push(`movies/${genres}/${page}`); }, [dispatch, language, page, genres, history]); const { popularMovies, numOfPages, isLoading } = useSelector( (state) => state.movies ); //Change Category const changeCategoryHandler = (id) => { setPage(1); setGenres(id); getCategoryName(id); }; //Print categories const frenchCategories = categoriesMoviesFR.map((category) => ( <li onClick={() => changeCategoryHandler(category.id)} id={category.id}> {category.name} </li> )); ... }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

The problem is that if i am on page 3 for example, and i press the browser's back button to return to page 2, I see that the link changes in the browser but the component is not updated. Same thing with the genres. If I quit Action for Adventure and hit the back button to go back to Action, I see the link changes but the component is not refreshed.

Has anyone ever encountered this kind of problem? Thank you for any help you can offer

The problem is here:

  const { genreID, pageNumber } = useParams();
  const [genres, setGenres] = useState(genreID);
  const [page, setPage] = useState(pageNumber);

You are initialising your state with dynamic props value, but state's default value will never change, because useState is only called once. You can try printing out genreID and pageNumber , and genres & page to find out that.

Solution

You can directly use { genreID, pageNumber } throughout your Movies component. If you really need to store them in state, use useEffect like this:

useEffect(()=>{
  setGenres(genreID)
  setPage(pageNumber)
},[genreID, pageNumber])

I made a very simple demo for you to have a clear vision on this type of problem.

So the index.js file looks like this

 import React from "react"; import ReactDOM from "react-dom"; import App from "./App"; import { createStore, applyMiddleware, compose } from "redux"; import { Provider } from "react-redux"; import rootReducer from "./reducers"; import thunk from "redux-thunk"; import { BrowserRouter } from "react-router-dom"; const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; const store = createStore(rootReducer, composeEnhancer(applyMiddleware(thunk))); ReactDOM.render( <BrowserRouter> <React.StrictMode> <Provider store={store}> <App /> </Provider> </React.StrictMode> </BrowserRouter>, document.getElementById("root") );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM