How to sync firebase with react functional components

Viewed 249

I would like to sync my component React with Firebase but i use a functional component i found somes answers in internet but it's seems complicated and doesn't worked for me and i can't use this : useEffect(() => { base.syncState('/', { context: this, state: 'messages' }) });

my code is

import React,{useEffect, useState} from 'react'
import Formulaire from './component/Formulaire'
import Message from './component/Message'
import {useParams} from 'react-router-dom'
import database from './Base'
import { getDatabase, ref, set,onValue } from "firebase/database";

function App() {
  const [state , setState] = useState({
    messages : {},
    pseudo : useParams().pseudo,
  })
  const addMessage = (message) =>{
    state.messages[`message-${Date.now()}`] = message
    setState({pseudo : state.pseudo ,messages : state.messages})
  }

    const msg = Object.keys(state.messages)
    const lastMessages = msg.map(key=>{
      return <Message key={key} pseudo={state.messages[key].pseudo} message = {state.messages[key].message} />
    })
  return (
    <div className="container-lg col-4 mt-5">
      <div>
        {lastMessages}
      </div>
      <Formulaire length={150} addMessage ={addMessage} pseudo={state.pseudo} />
    </div>
  )
}



export default App

And my firebaseApp code :

import { initializeApp } from 'firebase/app';
import { getDatabase } from "firebase/database";

// TODO: Replace with your app's Firebase project configuration
const firebaseConfig = {
  apiKey: "AIzaSyB2CFjr32PoNdsnfvEgt_AijgE18lNKz2c",
  authDomain: "chat-app-42ed5.firebaseapp.com",
  projectId: "chat-app-42ed5",
  storageBucket: "chat-app-42ed5.appspot.com",
  messagingSenderId: "880643875911",
  appId: "1:880643875911:web:9d04114b45bb40c2627d62",
  measurementId: "G-MP1VZCGRDP"
};

const app = initializeApp(firebaseConfig);

// Get a reference to the database service
const database = getDatabase(app);

export default database
2 Answers

When you mount the App component, you can open a snapshot listener to RTDB, see docs. You do that in useEffect and also return a function from useEffect to destroy the listener when your component gets unmounted. It's called a "cleanup function", see React docs

It would look something like that:

function App() {
 useEffect(() => {
    const unsubListener = onValue(ref(rtdb_instance, '/YOUR_PATH'), (snapshot) => {
      // Probably iterate over `snapshot.val()` and store it in your state
    })

    // Return cleanup function
    return unsubListener;
 }, [])
}

Note that the dependency array is empty here, meaning it won't change. Hence, it will only be executed on inital mount.

Also please note that the code above is not tested, so your milage might vary.

I use my function writeUserData() in AddMessage function after submit message to send to REALTIME DATABASE not in UseEffect() and after to get message after refresh page i use onValue() as you say in UseEffect() and in the same time i update my state with setState() ex: if (data) { setState({messages : data.messages , pseudo : state.pseudo}) } return

import React,{useState,useEffect} from 'react'
import Formulaire from './component/Formulaire'
import Message from './component/Message'
import {useParams} from 'react-router-dom'
import database from './Base'
import { ref, set,onValue } from "firebase/database";

function App() {

  const [state , setState] = useState({
    messages : {},
    pseudo : useParams().pseudo,
  })
  
  useEffect(()=>{
  const resultDb = ref(database);
  onValue(resultDb, (snapshot) => {
  const data = snapshot.val();
  if (data) {
    setState({messages : data.messages , pseudo : state.pseudo})
  } return 
})
   return resultDb
  },[])

  function writeUserData(message) {
    set(ref(database), {
      messages :message
    });
  }

  const addMessage = (message) =>{
    state.messages[`message-${Date.now()}`] = message
    setState({pseudo : state.pseudo ,messages : state.messages})
    writeUserData(state.messages)
  }

  const msg = Object.keys(state.messages)
  const lastMessages = msg.map(key=>{
    return <Message key={key} pseudo={state.messages[key].pseudo} message = {state.messages[key].message} />
    })
  return (
    <div className="container-lg col-4 mt-5">
      <div>
        {lastMessages}
      </div>
      <Formulaire length={150} addMessage ={addMessage} pseudo={state.pseudo} />
    </div>
  )
}

export default App
Related