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;
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