React and Firebase connection for get data and post data - javascript

I want to put the data in Firebase between li tags. For example; Room Code: {roomCode} but I cannot access the data I received from Firebase as I want.
This is the only way I can see the data in the console:
import React, {useState, useEffect, Component} from "react";
import fire from './fire';
function DataConnection() {
const [rooms, setRooms] = useState();
useEffect(() => {
const db = fire.firestore();
return db.collection('rooms').onSnapshot((snapshot) => {
const postData = [];
snapshot.forEach((doc) => postData.push({...doc.data(), id:doc.id}));
setRooms(postData);
});
}, []);
console.log(rooms);
return(
<div>
</div>
);};
export default DataConnection;

Theres nowhere in the code you are mapping the results of rooms into you return statement
function DataConnection() {
const [rooms, setRooms] = useState();
useEffect(() => {
const db = fire.firestore();
return db.collection('rooms').onSnapshot((snapshot) => {
const postData = [];
snapshot.forEach((doc) => postData.push({...doc.data(), id:doc.id}));
setRooms(postData);
});
}, []);
console.log(rooms);
rooms.map((el) => {
return (<><li>Roomname: { el.roomName} </li><li>Roomcode: {el.roomCode}</li></>)
}

Related

Can I do client side fetching inside the server side render component?

Can I perform client-side data fetching inside a component that's being rendered on a server-side rendered page? I have a page located at pages/solution/[solutionId]/index.js, which is server-side rendered, and it contains three components that should be performing client-side fetching. However, I am not getting any data, and it is returning null.
index.js
const Solution = ({ solution }) => {
const [isOpen, setIsOpen] = useState(false)
const router = useRouter()
const { id } = router.query
const { user } = useAuthContext()
return (
<>
<div className="px-5 row-start-2 row-end-3 col-start-2 col-end-3 mb-4">
// doing client-side fetching
<ShowWebsite
url={solution?.liveWebsiteUrl}
github={solution?.githubUrl}
title={solution?.title}
isPlayground={solution?.isPlayground}
/>
<div className="grid grid-col-1 md:grid-cols-[1fr_160px] items-start gap-x-5 mt-10">
<SolutionComments /> // doing client side fetching
<EmojiSection /> // doing client side fetching
</div>
</div>
</>
)
}
export default Solution
export async function getServerSideProps({ query }) {
const { solutionId } = query
console.log(solutionId)
const solution = await getDocument("solutions", solutionId)
return {
props: {
solution,
},
}
}
SolutionsComment:
import { useState } from "react"
import { useRouter } from "next/router"
import { useCollection } from "../../hooks/useCollection"
import Comment from "./Comment"
import CommentForm from "./CommentForm"
const SolutionComments = () => {
const router = useRouter()
const { id } = router.query
const { documents } = useCollection(`solutions/${id}/comments`)
return (
<div className="mt-10 md:mt-0">
<CommentForm docID={id} />
<div className="mt-10">
{documents &&
documents.map((comment) => (
<Comment
key={comment.id}
comment={comment}
replies={comment.replies}
/>
))}
</div>
</div>
)
}
EmojiSection:
import React from "react"
import { useRouter } from "next/router"
import { useDocument } from "../../hooks/useDocument"
import Emoji from "./Emoji"
const EmojiSection = () => {
const router = useRouter()
const { id: docID } = router.query
const { document: reactions } = useDocument(`solutions/${docID}/reactions`, "emojis")
console.log(reactions)
return (
// JSX CODE
)
}
useCollection:
import { collection, onSnapshot} from "firebase/firestore"
export const useCollection = (c) => {
const [documents, setDocuments] = useState([])
const [isLoading, setIsLoading] = useState(true)
const [error, setError] = useState(null)
useEffect(() => {
let ref = collection(db, c)
const unsubscribe = onSnapshot(ref, (snapshot) => {
const results = []
snapshot.docs.forEach(
(doc) => {
results.push({ ...doc.data(), id: doc.id })
},
(error) => {
console.log(error)
setError("could not fetch the data")
}
)
// update state
setDocuments(results)
setIsLoading(false)
setError(null)
})
return () => unsubscribe()
}, [])
return { documents, error, isLoading }
}

LocalStorage does not save after page refresh (React context)

I am developing a context in which through a function I can send "pokemons" to a global array, and also send the information of this array to my localstorage so that it is saved in the browser, I managed to do that and the array items are in localstorage, but every time the site refreshes, localstorage goes back to the empty array.
import React, { useEffect, useState } from "react";
import CatchContext from "./Context";
const CatchProvider = ({ children }) => {
const [pokemons, setPokemons] = useState([], () => {
const dataStorage = localStorage.getItem('pokemons');
if (dataStorage) {
return JSON.parse(dataStorage)
} else {
return [];
}
});
useEffect(() => {
localStorage.setItem('pokemons', JSON.stringify(pokemons));
}, [pokemons]);
const updatePokemons = (name) => {
const updatedPokemons = [...pokemons];
const pokemonsIndex = pokemons.indexOf(name);
if (pokemonsIndex >= 0) {
updatedPokemons.slice(pokemonsIndex, 1)
} else {
updatedPokemons.push(name)
};
setPokemons(updatedPokemons)
}
const deletePokemon = async (name) => {
await pokemons.splice(pokemons.indexOf(toString(name)))
}
return (
<CatchContext.Provider value={{ pokemons: pokemons, updatePokemons: updatePokemons, deletePokemon: deletePokemon }}>
{children}
</CatchContext.Provider>
);
}
export default CatchProvider;
The problem is that useState doesn't take two arguments.
Instead of:
const [pokemons, setPokemons] = useState([], () => {
You want:
const [pokemons, setPokemons] = useState(() => {
I think you don't need to call useEffect on initial render so you can make use of refs for this
import { useEffect, useRef } from "react";
// other code....
const didMount = useRef(false);
useEffect(() => {
if (didMount.current) {
localStorage.setItem('pokemons', JSON.stringify(pokemons));
} else {
didMount.current = true;
}
}, [pokemons]);

How to send array of items to localstorage within context api? (REACT)

I'm developing a pokedex using pokeAPI through react, but I'm developing a feature where I can favorite pokemons and with that through a context, I can store the names of these pokemons in a global array. I've already managed to test and verify that the pokemon names are going to this "database" array inside the pokeDatabase const in my context, but my goal now is to pass this array to localstorage so that the browser recognizes these favorite pokemons instead of disappearing every time I refresh the page, my solution was to try to create a useEffect inside the context so that every time I refresh my application, this information is saved in localStorage, but without success. What better way to achieve this?
context:
import { createContext } from "react";
const CatchContext = createContext({
pokemons: null,
});
export default CatchContext;
provider
import React, { useEffect } from "react";
import CatchContext from "./Context";
const pokeDatabase = {
database: [],
};
const CatchProvider = ({ children }) => {
useEffect(() => {
const dataStorage = async () => {
await localStorage.setItem('pokemons', JSON.stringify(pokeDatabase.database));
}
dataStorage();
}, [])
return (
<CatchContext.Provider value={{ pokemons: pokeDatabase }}>
{children}
</CatchContext.Provider>
);
}
export default CatchProvider;
pageAddPokemon
import * as C from './styles';
import { useContext, useEffect, useState } from 'react';
import { useApi } from '../../hooks/useApi';
import { useNavigate, useParams } from 'react-router-dom';
import PokeInfo from '../../components/PokeInfo';
import AddCircleOutlineIcon from '#mui/icons-material/AddCircleOutline';
import DoNotDisturbOnIcon from '#mui/icons-material/DoNotDisturbOn';
import CatchContext from '../../context/Context';
const SinglePokemon = () => {
const api = useApi();
const { pokemons } = useContext(CatchContext);
const { name } = useParams();
const navigate = useNavigate();
const handleHompage = () => {
navigate('/');
}
const [loading, setLoading] = useState(false);
const [imgDatabase, setImgDatabase] = useState('');
const [infoPokemon, setInfoPokemon] = useState([]);
const [pokemonTypes, setPokemonTypes] = useState([]);
const [isCatch, setIsCatch] = useState(false);
useEffect(() => {
const singlePokemon = async () => {
const pokemon = await api.getPokemon(name);
setLoading(true);
setImgDatabase(pokemon.sprites);
setInfoPokemon(pokemon);
setPokemonTypes(pokemon.types);
setLoading(false);
console.log(pokemons.database);
}
singlePokemon();
verifyPokemonInDatabase();
}, []);
const verifyPokemonInDatabase = () => {
if (pokemons.database[infoPokemon.name]) {
return setIsCatch(true);
} else {
return setIsCatch(false);
}
}
const handleCatchAdd = async () => {
if (isCatch === false) {
if (!pokemons.database[infoPokemon.name]);
pokemons.database.push(infoPokemon.name);
setIsCatch(true);
}
}
const handleCatchRemove = async () => {
if (isCatch === true) {
if (!pokemons.database[infoPokemon.name]);
pokemons.database.splice(pokemons.database.indexOf(toString(infoPokemon.name)), 1);
setIsCatch(false);
}
}
return (
<C.Container>
<PokeInfo
name={infoPokemon.name}
/>
<C.Card>
<C.Info>
<C.Imgs>
<img src={imgDatabase.front_default} alt="" />
<img src={imgDatabase.back_default} alt="" />
</C.Imgs>
<h2 id='types'>Tipos</h2>
{pokemonTypes.map(type => {
return (
<C.Types>
<h2>{type.type.name}</h2>
</C.Types>
)
})}
{isCatch ? (
<DoNotDisturbOnIcon id='iconCatched' onClick={handleCatchRemove}/>
): <AddCircleOutlineIcon id='icon' onClick={handleCatchAdd}/>}
</C.Info>
</C.Card>
<C.Return>
<button onClick={handleHompage}>Retornar a Pokédex</button>
</C.Return>
</C.Container>
)
}
export default SinglePokemon;

Array doesn't save information ReactJS

import './App.css';
import io from 'socket.io-client'
import { useEffect, useRef, useState } from 'react'
import React from 'react';
import ReactDOM from "react-dom/client";
const socket = io.connect("http://localhost:3001");
function App() {
const [message, setMessage] = useState("");
const [state, setState] = useState([]);
const [chat, setChat] = useState([]);
const socketRef = useRef();
const sendMessage = () => {
socket.emit("send_message", { message });
};
const renderChat = () => {
return (
chat.map(msg => {
console.log(msg.data)
return (
<h3>{msg.data["message"]}</h3>
)
})
)
}
useEffect(() => {
socketRef.current = io.connect("http://localhost:3001")
socketRef.current.on("receive_message", ({ message }) => {
setChat([ ...chat, { message } ])
})
return () => socketRef.current.disconnect()
},
[ chat ]
)
return (
<div className="App">
<input placeholder="Message..." onChange={(event) => {
setMessage(event.target.value);}}
/>
<button onClick={sendMessage}>Send Message</button>
<h1>Message:</h1>
{renderChat()}
</div>
);
}
export default App;
For some reason the useEffect that needs to store information doesn't work. I have tried a few solutions to store new values in an array useState but I always get this error:
When I do it like this:
useEffect(() => {
socket.on("receive_message", message => {
setChat([...chat, {message}]);
});
}, [socket])
it works but it doesn't save the information (it always has only 1 value which is the latest input text).
You can do it like in the second approach you mentioned, using the previous State:
useEffect(() => {
socket.on("receive_message", message => {
setChat(prevState => [...prevState, {message}]);
});
}, [socket])
You try
useEffect(() => {
socket.on("receive_message", ({ message }) => {
if(!!message){
setChat(prev => [ ...prev, { message } ])
}
})
return () => socket.disconnect()
},[ socket ])

How to fetch data instantly after post request - useEffect react

I want to know if that is the correct way i do it.
Firstly i fetch the hard coded data from my API and display it into the screen. I also have a form from which i send data and i want the axios.get method to instantly fetch the newest updated data that was sent from a form. I made a helper state that is put in to "useEffect array dependencies" and whenever that state changes its value, app reloads and fetches again.
Context file with useEffect hook:
import { createContext, useState, useEffect } from "react";
import { apiService } from "../services/api/api.service";
const Context = createContext({
footer: false,
subjectForm: false,
storedSubjects: [],
footerVisibilityHandler: () => {},
subjectFormVisibilityHandler: () => {},
});
export const ContextProvider = ({ children }) => {
const [footer, setFooter] = useState(false);
const [subjectForm, setSubjectForm] = useState(false);
const [storedSubjects, setStoredSubjects] = useState([]);
const [send, setSend] = useState(false);
useEffect(() => {
const getData = async () => {
try {
const getSubjects = await apiService.getSubjects();
const tableRow = getSubjects.data.map((subject) => {
return {
name: subject.name,
};
});
setStoredSubjects(tableRow);
} catch (err) {
console.log(err);
}
};
getData();
}, [send]);
const footerVisibilityHandler = () => {
setFooter((previousState) => !previousState);
setSubjectForm(false);
};
const subjectFormVisibilityHandler = () => {
setSubjectForm((previousState) => !previousState);
};
const context = {
footer,
subjectForm,
storedSubjects,
footerVisibilityHandler,
subjectFormVisibilityHandler,
setSend,
};
return <Context.Provider value={context}>{children}</Context.Provider>;
};
export default Context;
Form from which i send data:
import Context from "../../store/context";
import FormContainer from "../UI/FormContainer";
import { apiService } from "../../services/api/api.service";
import { useContext, useRef } from "react";
const AddSubject = () => {
const ctx = useContext(Context);
const subject = useRef("");
const sendData = (e) => {
e.preventDefault();
ctx.setSend((prevState) => !prevState);
apiService.addSubject(subject.current.value);
};
return (
<FormContainer show={ctx.subjectForm} send={sendData}>
<label htmlFor="subject">Subject Name: </label>
<input type="text" id="subject" ref={subject} />
<button type="submit">Add</button>
</FormContainer>
);
};
export default AddSubject;
Api endpoints file:
import axios from "axios";
const api = () => {
const baseUrl = "https://localhost:5001/api";
let optionAxios = {
headers: {
"Content-Type": "multipart/form-data",
},
};
return {
getSubjects: () => axios.get(`${baseUrl}/subjectcontroller/getsubjects`),
addSubject: (subjectName) =>
axios.post(
`${baseUrl}/subjectcontroller/createsubject`,
{
name: subjectName,
},
optionAxios
),
};
};
export const apiService = api();

Categories