Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

114
Vistas
Scroll to anchor when Component is fully rendered in React functional component

This a (very) simplified version of my component:

export const DynamicComponent: FC<DynamicComponentProps> = (props) => {
  const ref = useRef<HTMLElement>(null);
  const [isSticked, setIsSticked] = useState(false);
  const parentSticked = useContext(StickyContext);
  const [overridedStyles, setOverridedStyles] = useState(props.styles ?? {});
  const [overridedArgs, setOverridedArgs] = useState(props.args ?? {});
  const { config } = useContext(GlobalContext);
  const data = useContext(DataContext);
  const [state, setState] = useContext(StateContext);

  const mountComponent = useMemo(() => {
    if (typeof props.mount === "undefined") return true;
    if (typeof props.mount === "boolean") return props.mount;
    if (typeof props.mount === "number") return props.mount === 1;
    if (typeof props.mount === "string") {
      let mount = stateParser.parse(props.mount, state) as unknown;
      return mount == true;
    }
    return false;
  }, [state, props.mount]);



  useLayoutEffect(() => {
    setTimeout(() => {
      const anchorHash = location.hash;
      if (
        anchorHash &&
        document &&
        document.querySelector(anchorHash) &&
        !document
          .querySelector(anchorHash)
          ?.classList.contains("already-scrolled")
      ) {
        document?.querySelector(anchorHash)?.scrollIntoView();
        document?.querySelector(anchorHash)?.classList.add("already-scrolled");
      }
    }, 50);
  }, []);

  let output = mountComponent ? (
    <StickyContext.Provider value={{ sticked: isSticked }}>
      <StyledDynamicComponent
        {...props}
        ref={ref}
        isSticked={applyStickedStyles}
        args={overridedArgs}
        styles={overridedStyles}
      />
    </StickyContext.Provider>
  ) : null;

  return output;
};

The code inside the useLayoutEffect won't run correctly without the setTimeout because the component is not fully rendered and document?.querySelector(anchorHash) does not exist yet..

Tried with a window.onload but the code inside it will never run..

Is there a way to prevent using that horrendous setTimeout?

Also please note that the anchor or the anchored element are optional so I don't know how to use callaback refs

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

Don't use document.querySelector and don't check class names, if you can use states for it.

You don't need setTimeout at all, as useEffect and useEffectLayout are more or less the same as componentDidMount:

If you’re migrating code from a class component, note useLayoutEffect fires in the same phase as componentDidMount and componentDidUpdate. However, we recommend starting with useEffect first and only trying useLayoutEffect if that causes a problem. useLayoutEffect-Docs

I tried to reduce your samle a little bit more and made it debuggable in the codesandbox (hopefully keeping your logic in tact).

Edit React PlayGround (forked)

But the most important part would be the following:

const ref = useRef();

useEffect(() => {
    if (!ref.current || !document) {
      return;
    }

    // check if a hash is provided
    // possible todo: is the current element id the same as the provided location hash id
    if(!location.hash) {
      return true;
    }

    // check if we've scrolled already
    if(scrolled) {
      return;
    }

    ref.current.scrollIntoView();

    console.log("scroll to view", ref);
    setScrolled(true);
}, [ref, location, scrolled]);


Your component will then be rendered each time, the ref, location, or scrolled vars have changed, but it should only scroll into view, if it hasn't done that before.

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda