0

The code persistently Data stores in Firebase which is what I wanted after each session, but it's hacky because setOnes([...ones,1]) and writeToFirebase shouldn't be called under the same functions due to async, but every time I tried with useEffect(()=>writeToFirebase(),[setOnes]) to achieve similar result as ComponentDidUpdate, it got triggered right at the beginning of the launch and reset to FB database back to [1,1]. This is the code I have, codesandbox link: https://codesandbox.io/s/super-simple-react-firebase-functional-class-hook-set-up-eyo15?file=/src/App2.js:279-326

const App2 = () =>{
  
  const [ones, setOnes] = useState([1,1]);
  useEffect(() => {
    Firebase.initializeApp(config)
    getFromFirebase()
  }, []);

  // useEffect(()=>writeToFirebase(),[setOnes])

  const writeToFirebase = () => {
    Firebase.database()
      .ref("/")
      .set(ones);
    console.log("DATA SAVED");
  };

  const getFromFirebase = () => {
    let ref = Firebase.database().ref("/");
    ref.on("value", snapshot => {
      const state = snapshot.val();
      setOnes(state)
    })
  }

  const handleAdd =() => {
    setOnes([...ones,1])
    writeToFirebase()
  }
    
    const list = ones.map((e,i)=>( 
        <div
            key={e.id}
        > {e} </div>
    ))
  
    return ( 
    <div>
      {list}
      <button onClick={handleAdd}>Add</button>
    </div> 
    )
}

export default App2;
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
carter x
  • 35
  • 3

2 Answers2

0

You should write useEffect(()=>writeToFirebase(),[ones]) instead of // useEffect(()=>writeToFirebase(),[setOnes])

useEffect(()=>writeToFirebase(),[ones]) means that writeToFirebase will execute each time ones change. ones is the state variable here, setOnes is a function.

Aman
  • 11
  • 2
  • Sorry I have tried that, but it doesn't seem to work, I think when `setOnes`, it also changes the state of `Ones`, so useEffect still runs `writeToFirebase()` at the beginning of the launch... – carter x Apr 03 '21 at 22:22
  • Thanks for your answer, this is the fix to my code const isInitialMount = useRef(true); useEffect(() => { if (isInitialMount.current) { isInitialMount.current = false; } else { writeToFirebase() } },[ones]); – carter x Apr 03 '21 at 22:30
0

Do not use setones as a dependency in useEffect, use ones. Full Code will look like this

const App2 = () =>{
  
  const [ones, setOnes] = useState([1,1]);
  useEffect(() => {
    Firebase.initializeApp(config)
    getFromFirebase()
  }, []);

  useEffect(()=>writeToFirebase(),[ones])

  const writeToFirebase = () => {
    Firebase.database()
      .ref("/")
      .set(ones);
    console.log("DATA SAVED");
  };

  const getFromFirebase = () => {
    let ref = Firebase.database().ref("/");
    ref.on("value", snapshot => {
      const state = snapshot.val();
      setOnes(state)
    })
  }

  const handleAdd =() => {
    setOnes([...ones,1])
  }
    
    const list = ones.map((e,i)=>( 
        <div
            key={e.id}
        > {e} </div>
    ))
  
    return ( 
    <div>
      {list}
      <button onClick={handleAdd}>Add</button>
    </div> 
    )
}

export default App2;

Altenatively, if you want to call writeToFirebase() only when ones change and not on initial render, you can use a custom hook useDidUpdateEffect. You can find the code in the answer to this question React hooks useEffect only on update?. In that case the full code will look like this

const App2 = () =>{
  
  const [ones, setOnes] = useState([1,1]);
  const isInitialMount = useRef(true);
  useEffect(() => {
    Firebase.initializeApp(config)
    getFromFirebase()
  }, []);

  
  useEffect(() => {
  if (isInitialMount.current) {
       isInitialMount.current = false;
     } else {
     writeToFirebase();
    }
  }, [ones]);

  const writeToFirebase = () => {
    Firebase.database()
      .ref("/")
      .set(ones);
    console.log("DATA SAVED");
  };

  const getFromFirebase = () => {
    let ref = Firebase.database().ref("/");
    ref.on("value", snapshot => {
      const state = snapshot.val();
      setOnes(state)
    })
  }

  const handleAdd =() => {
    setOnes([...ones,1])
  }
    
    const list = ones.map((e,i)=>( 
        <div
            key={e.id}
        > {e} </div>
    ))
  
    return ( 
    <div>
      {list}
      <button onClick={handleAdd}>Add</button>
    </div> 
    )
}

export default App2
Josh
  • 827
  • 5
  • 7