Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getSnapshotBeforeUpdate using react hooks

How can I implement the same logic that getSnapshotBeforeUpdate gives me using react hooks?

like image 470
Luke Avatar asked Nov 29 '18 11:11

Luke


People also ask

What is the replacement of getSnapshotBeforeUpdate () method in hooks?

Well, the answer is no. There are no Hook equivalents for the getSnapshotBeforeUpdate and componentDidCatch class lifecycle methods. To be fair, these methods aren't used as much as the others – regardless they are still helpful lifecycle methods and the React team had promised to release this “soon”.

What is the purpose of getSnapshotBeforeUpdate () & lifecycle method?

getSnapshotBeforeUpdate()It enables your component to capture some information from the DOM (e.g. scroll position) before it is potentially changed. Any value returned by this lifecycle method will be passed as a parameter to componentDidUpdate() .

How do you fetch data using React hooks?

Put the fetchData function above in the useEffect hook and call it, like so: useEffect(() => { const url = "https://api.adviceslip.com/advice"; const fetchData = async () => { try { const response = await fetch(url); const json = await response. json(); console. log(json); } catch (error) { console.

Are React hooks still used?

React hooks have been around for some time now, yet many React developers are not actively using them.


2 Answers

As per the React Hooks FAQ, there isn't a way to implement getSnapshotBeforeUpdate and ComponentDidCatch lifecycle method with hooks yet

Do Hooks cover all use cases for classes?

Our goal is for Hooks to cover all use cases for classes as soon as possible. There are no Hook equivalents to the uncommon getSnapshotBeforeUpdate and componentDidCatch lifecycles yet, but we plan to add them soon.

It is a very early time for Hooks, so some integrations like DevTools support or Flow/TypeScript typings may not be ready yet. Some third-party libraries might also not be compatible with Hooks at the moment.

like image 172
Shubham Khatri Avatar answered Oct 29 '22 05:10

Shubham Khatri


We cannot get the snapshot data in any of the hooks (useLayoutEffect or useEffect) as both will give the updated DOM values by the time they are triggered, the best place to capture the data is just before the setting the state. for example here I am capturing the scroll position before setting the state.

function ChatBox(props){

  const [state, setState] = useState({chatFetched:[],isFetching:false});

  const listRef = useRef();
  const previousScrollDiff = useRef(0);
  
  // on mount 
  useEffect(()=>{
    getSomeMessagesApi().then(resp=>{
      const chatFetched = [...state.chatFetched,...resp];
      setState({chatFetched});
    })
  },[]);

  useLayoutEffect(()=>{
   // use the captured snapshot here
   listRef.current.scrollTop = listRef.current.scrollHeight - previousScrollDiff.current;

  },[state.chatFetched])
  
  useEffect(()=>{

    // don't use captured snapshot here ,will cause jerk effect in scroll

  },[state.chatFetched]);


  const onScroll = (event) => {
    const topReached = (event.target.scrollTop === 0);

    if(topReached && !state.isFetching){

      setState({...state, isFetching:true});

      getSomeMessagesApi().then(resp=>{
        const chatFetched = [...resp,...state.chatFetched];

        // here I am capturing the data ie.., scroll position

        previousScrollDiff.current = listRef.current.scrollHeight -listRef.current.scrollTop;
        setState({chatFetched, isFetching:false});
      })
    }
  }

  return (  
    <div className="ui container">
      <div 
        className="ui container chat list" 
        style={{height:'420px', width:'500px',overflow:'auto'}}
        ref={listRef}
        onScroll={onScroll}
        >
          {state.chatFetched.map((message)=>{
           return <ChatLi data ={message} key ={message.key}></ChatLi>
          })}
      </div>  
    </div>
   ); 
};

we can also useMemo to capture the data before dom update happens,

function ChatBox(props){

  const [state, setState] = useState({chatFetched:[],isFetching:false});

  const listRef = useRef();
  const previousScrollDiff = useRef(0);
  
  // on mount 
  useEffect(()=>{
    getSomeMessagesApi().then(resp=>{
      const chatFetched = [...state.chatFetched,...resp];
      setState({chatFetched});
    })
  },[]);

  useLayoutEffect(()=>{
   // use the captured snapshot here
   listRef.current.scrollTop = listRef.current.scrollHeight - previousScrollDiff.current;

  },[state.chatFetched])
  
  useEffect(()=>{

    // don't use captured snapshot here ,will cause jerk effect in scroll

  },[state.chatFetched]);

  useMemo(() => {
   // caputure dom info in use effect
    if(scrollUl.current){
       previousScrollDiff.current = scrollUl.current.scrollHeight - scrollUl.current.scrollTop;
    }
    
  }, [state.chatFetched]);

  const onScroll = (event) => {
    const topReached = (event.target.scrollTop === 0);

    if(topReached && !state.isFetching){

      setState({...state, isFetching:true});

      getSomeMessagesApi().then(resp=>{
        const chatFetched = [...resp,...state.chatFetched];
        setState({chatFetched, isFetching:false});
      })
    }
  }

  return (  
    <div className="ui container">
      <div 
        className="ui container chat list" 
        style={{height:'420px', width:'500px',overflow:'auto'}}
        ref={listRef}
        onScroll={onScroll}
        >
          {state.chatFetched.map((message)=>{
           return <ChatLi data ={message} key ={message.key}></ChatLi>
          })}
      </div>  
    </div>
   ); 
};

In the above examples I am trying to do the same that is shown here in the getSnapshotBeforeUpdate react doc

like image 25
MOHANTEJA Avatar answered Oct 29 '22 04:10

MOHANTEJA