简体   繁体   中英

Why setState in useEffect in not updating to the ref.current value supplied to it?

What I want: to get element( <ul> ) scrollwidth inside of the style attribute inside DOM

What I am trying:

The setSliderScrollWidth in useEffect should update the state for sliderScrollWidth , the sliderEl.current.scrollWidth value is avaiable inside of the useEffect, but still inside of useEffect the sliderScrollWidth is 0.

Also I can not get sliderEl.current.scrollWidth inside of the DOM, so I am unable to get the inside of DOM with either useState or useRef.

const TextSlider = () => {
  const sliderEl = useRef(null);
  const [sliderScrollWidth, setSliderScrollWidth] = useState(0);
 
  useEffect(() => {
    setSliderScrollWidth(sliderEl.current.scrollWidth);
    console.log(sliderScrollWidth, sliderEl.current.scrollWidth);
  },[])
 
  return(
     <ul
      ref={sliderEl}
      style={{
        width: `${sliderEl.current.scrollWidth}`,
      }}
    >
       <li>Hello</li>
    </ul>
  )
}

What I don't understand : 1) Why if I can get sliderEl.current.scrollWidth inside of useEffect the sliderScrollWidth value is still 0? 2) Why can't I get the ref.current value inside the DOM?

The setSliderScrollWidth in useEffect should update the state for sliderScrollWidth , the sliderEl.current.scrollWidth value is avaiable inside of the useEffect , but still inside of useEffect the sliderScrollWidth is 0.

Right, state updates are not immediate . In a hooks-based component, calling the state setter will eventually make React call your component function again, and when it does your component function will get the updated value from useState into the new constant created for that call.

Also I can not get sliderEl.current.scrollWidth inside of the DOM...

I assume you're referring to where you're trying to use it on the style prop. You can't do that, the element doesn't exist yet as of where you're trying to use sliderEl.current.scrollWidth , and sliderEl doesn't have a reference to it yet (because it doesn't exist).

You can set sliderEl.current.style.width in the effect callback, because at that point the DOM element will exist and sliderEl will have it:

const TextSlider = () => {
  const sliderEl = useRef(null);
 
  useEffect(() => {
    sliderEl.current.style.width = `${sliderEl.current.scrollWidth}px`;
  },[]);
 
  return(
     <ul
      ref={sliderEl}
    >
       <li>Hello</li>
    </ul>
  );
};

That's one of the purpose of useEffect (or useLayoutEffect , in some cases): To apply information to the DOM element you can't apply earlier.

I think this little change can help you

In the end of useEffect put ,[sliderScrollWidth]

const TextSlider = () => {
  const sliderEl = useRef(null);
  const [sliderScrollWidth, setSliderScrollWidth] = useState(0);
 
  useEffect(() => {
    setSliderScrollWidth(sliderEl.current.scrollWidth);
    console.log(sliderScrollWidth, sliderEl.current.scrollWidth);
  },[sliderScrollWidth])
 
  return(
     <ul
      ref={sliderEl}
      style={{
        width: `${sliderScrollWidth}`,
      }}
    >
       <li>Hello</li>
    </ul>
  )
}

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