Je recherche une solution pour enregistrer le changement d'itinéraire et appliquer de nouveaux state
en utilisant setState
et useEffect
. Le code actuel ci-dessous ne met pas à jour les fonctions de setState
lorsque l'itinéraire est modifié.
Par exemple, j'enregistre le pathname
de /
Avec location.pathname === '/'
Dans createContext
, si le pathname
est /
Le setState
de isHome
est enregistré true
, cependant si pathname
est /page-1
setState
est enregistré false
.
Lors des rechargements du navigateur, onMount
le state
est correctement défini, mais ce n'est pas le cas lors d'un changement d'itinéraire utilisant Link
. Veuillez également noter que j'utilise Gatsby et, ce faisant, j'importe { Link } from 'gatsby'
CreateContext.js
export const GlobalProvider = ({ children, location }) => {
const prevScrollY = useRef(0);
const [state, setState] = useState({
isHome: location.pathname === '/',
// other states
});
const detectHome = () => {
const homePath = location.pathname === '/';
if (!homePath) {
setState(prevState => ({
...prevState,
isHome: false
}));
}
if (homePath) {
setState(prevState => ({
...prevState,
isHome: true
}));
}
};
useEffect(() => {
detectHome();
return () => {
detectHome();
};
}, [state.isHome]);
return (
<GlobalConsumer.Provider
value={{
dataContext: state,
}}
>
{children}
</GlobalConsumer.Provider>
);
};
Si je console.log(state.isHome)
sur pathname
/
J'obtiens true
, tout autre chemin que j'obtiens false
, cependant, si je change de route, l'état actuel de isHome
reste précédent, jusqu'à ce que je défile et que useEffect
s'applique.
L'enregistrement de l'état isHome
a pour but de modifier le CSS par page.
Comment puis-je mettre à jour l'état avec useEffect
lors du changement de route. Auparavant, j'aurais fait cela avec componentDidUpdate
et enregistré prevProps.location.pathname
Contre props.location.pathname
, Cependant, je crois comprendre que ce n'est plus nécessaire avec le crochet useEffect
.
Si vous utilisez react-router, vous pouvez vous abonner à l'événement de changement d'emplacement dans votre utilisation
import {browserHistory} from 'react-router';
...
useEffect(() => {
return browserHistory.listen(detectHome);
}, []);
...
Cela souscrirait votre fonction detectHome
pour le changement d'emplacement lors du montage et la désinscrire lors du démontage.
Je pense que si vous utilisez GlobalProvider
comme composant racine, dans ce cas, il ne sera rendu qu'une seule fois, sauf si quelque chose change les états ou les accessoires. Donc, une explication:
useEffect(() => {
detectHome();
return () => {
detectHome();
};
}, [state.isHome]);
Ce code ci-dessus, le state
est mis à jour uniquement par ce useEffect
, donc il ne met à jour l'état qu'une seule fois après le premier rendu, et le detectHome
à l'intérieur du retour de useEffect
ne s'exécute que lorsqu'une autre mise à jour se produit ou que state.isHome
est différent de la première fois. C'est un peu confus cette explication, mais c'est.
Mais pour la solution, utilisez l'événement "popstate" de la fenêtre:
export const GlobalProvider = ({ children, location }) => {
const prevScrollY = useRef(0);
const [state, setState] = useState({
isHome: location.pathname === '/',
// other states
});
const detectHome = () => {
const homePath = location.pathname === '/';
if (!homePath) {
setState(prevState => ({
...prevState,
isHome: false
}));
}
if (homePath) {
setState(prevState => ({
...prevState,
isHome: true
}));
}
};
useEffect(() => {
window.addEventListener('popstate', detectHome)
return () => {
window.removeEventListener('popstate', detectHome)
};
}, [state.isHome]);
return (
<GlobalConsumer.Provider
value={{
dataContext: state,
}}
>
{children}
</GlobalConsumer.Provider>
);
};
Je pense que Gatsby devrait manipuler l'historique, donc cela déclenchera popstate
du navigateur, et vous pourrez détecter les changements de l'url.