React Native Unable to fetch multiple documents data from Firebase firestore - reactjs

App.js File this is App.js file, Please check the below code and correct me I don't have any idea how to solve this issue. Thank you in advance.
.doc("2E3kDAa0QzqoQuoBK1T9", "vROxKUSgcNWwlt7cDEKV") on this line I get the issue.
import React, { useState, useEffect } from "react";
import { View, Text } from 'react-native';
import firestore from '#react-native-firebase/firestore';
function App() {
const [myData, setMyData] = useState(null);
useEffect(() => {
getDatabase();
}, []);
const getDatabase = async () => {
try {
const data = await firestore()
.collection('myCollection')
.doc("2E3kDAa0QzqoQuoBK1T9", "vROxKUSgcNWwlt7cDEKV")
.get();
setMyData(data._data)
} catch (err) {
console.log(err);
}
};
return (
<View>
<Text>First:-{myData ? myData.name : 'Loading...'}</Text>
<Text>Second:-{myData ? myData.secondData : 'Loading...'}</Text>
</View>
);
}
export default App;

This doesn't work:
.doc("2E3kDAa0QzqoQuoBK1T9", "vROxKUSgcNWwlt7cDEKV")
If you check the API docs for CollectionReference.doc it expects:
doc(documentPath?: undefined | string): DocumentReference<>;
So you can pass in a single document ID or path, not multiple.
If you want to return multiple documents by their ID, you can use th in query operator on the FieldPath.documentId() to do so for up to 10 values. If you have more values, you'll need to retrieve them in batches of up to 10 and merge them in your application code.

Related

React real-time chart with react.context and socket.io

I'm trying to build a website for displaying real-time charts in typescript with react for my learning. But I can not get values from a server properly before displaying the chart.
What I want to do is ...
Communication protocol is websocket using socket.io.
Using socket.io and storing data are inside React.Context(useSocket.tsx) so as to access the data from any react components easily.
Displaying the data is in Home.tsx.
The socket events are initial_data and new_data.
The initial_data event is received at the time the accessing the website at first.
The new_data event is received at regularly.
The time getting both events above, update values inside Home.tsx automatically.
I researched some articles on the web, for example, explaining a way that using socket.io inside a useEffect() function that returning socket.disconnect().
So, the code I built is below.
useSocket.tsx
import {useContext, createContext, useState, useEffect} from "react";
import {io, Socket} from "socket.io-client";
import {chartDataType} from "../types/chartDataType";
type Context = {
chartData: Array<chartDataType>;
}
const SocketContext = createContext<Context>({
chartData: [],
});
const SocketsProvider = (props: any) => {
const [chartData, setChartData] = useState();
useEffect( () => {
const socket: Socket = io("http://***.***.***.***");
socket.on('initial_data', (data) => {
console.log(data);
setChartData(data);
});
socket.on('new_data', (data) => {
console.log(data);
});
return () => { socket.disconnect() };
},[]);
return (
<SocketContext.Provider value={{chartData}} {...props} />
);
}
const useSocket = () => useContext(SocketContext);
export { SocketsProvider, useSocket };
Home.tsx
import {memo, VFC} from "react";
import { useSocket } from "../../context/useSocket";
import {Heading} from "#chakra-ui/react";
export const Home: VFC = memo(() => {
const { chartData } = useSocket();
return (
<>
<Heading as="h1">{`${chartData}`}</Heading>
</>
)
})
The above code caused an error Uncaught TypeError: Cannot read properties of undefined (reading '0') occurred in the browser console. But when the comment out the <Heading>...</Heading> line in Home.tsx, the console.log in useSocket.tsx can display the value from the server in the browser console.
I can not come up with the idea for the correct implementation. Is the definition of the type of the chartData wrong? or other reasons? The definition of the chartDataType has nothing wrong.
What is the way for the correct implementation?
What's happening is you are trying to render an empty array, the data hasn't loaded yet.
You need to check if charData exists, or if it's undefined first.
Like this:
return (
{CharData ? <Heading /> ... : null }
)

How to parse input xml data to json in react with xml2js?

I am trying to parse the input xml data to json in react with the help of xml2js.
import React, { useState } from "react";
import xml2js from "xml2js";
function Parser() {
const [xmlData, setXmlData] = useState({});
let parser = new xml2js.Parser();
parser.parseString(
`<email>
<to>Test</to>
<from>Test1</from>
<heading>Test email</heading>
<body>Email regards to xml data parsing in React</body>
</email>`,
function (err, result) {
console.log(result);
if (result) {
setXmlData(result);
return;
}
return;
}
);
return (
<div>
Parse XML using ReactJs
{JSON.stringify(xmlData)}
</div>
);
}
export default Parser;
But I am getting unlimited re render error. Can anyone help on this ?
Thanks in advance
Since parseString is an asynchronous API, you will need to call it in an useEffect hook with the input data set as a dependency to avoid it being re-re-re-re-...-called on each render.
I also moved the input data to a prop here, for reusability.
import React, { useState } from "react";
import xml2js from "xml2js";
function Parser({ inputData }) {
const [xmlData, setXmlData] = React.useState(null);
React.useEffect(() => {
const parser = new xml2js.Parser();
parser.parseString(inputData, function (err, result) {
setXmlData(result);
});
}, [inputData]);
return (
<div>
Parse XML using ReactJs
{JSON.stringify(xmlData)}
</div>
);
}
export default Parser;
<Parser inputData={`<email>
<to>Test</to>
<from>Test1</from>
<heading>Test email</heading>
<body>Email regards to xml data parsing in React</body>
</email>`}
/>

How do I access React State properties using TypeScript? Get property does not exist on type error

I have defined a type, I get the expected data from my API. However, when I try access a property I get error Property 'deployed' does not exist on type 'Service[]'.. I'm confused because deployed is a property?
Here is my type:
export interface Service {
service: String,
deployed: String,
message: String[]
}
Here is API request:
import axios from 'axios';
import { apiBaseURL } from '../constants';
import { Service } from '../types'
export const getStatus = async () => {
const { data: status } = await axios.get<Service[]>(`${apiBaseURL}/status`);
return status;
}
Code with error:
import React from 'react';
import './App.css';
import { getStatus } from './services/status';
import { Service } from './types';
function App() {
const [status, setStatus] = React.useState<Service[]>([]);
React.useEffect(() => {
(async () => {
const response = await getStatus();
setStatus(response);
console.log(status);
})()
// eslint-disable-next-line
}, [])
return (
<div className="App">
<header className="App-header">
<h1>App</h1>
</header>
{status && (
<p>{status.deployed}</p>
)}
</div>
);
}
export default App;
This line:
const [status, setStatus] = React.useState<Service[]>([]);
Says, status is a an array of Service.
This line:
<p>{status.deployed}</p>
Says, you want access deployed method of that array. Which is wrong.
A possible way to check whether this hypothesis is right, would be to try to access deployed on an element of that array.
For example, assuming you have validated that there exists at least one element in status array, this:
<p>{status[0].deployed}</p>
or if you wanted to print all the deployed status, something like this:
{!!status && status.map(s => <p key={s.service}>{s.deployed}</p>)}
Service[] is an array. The array type does not have a property called deployed

React hooks useState getting diferrent value from redux state

I have react component look like this following code:
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Link, useParams } from "react-router-dom";
import { createClient, getClients } from "../redux/actions/clients";
function UpdateClient(props) {
let params = useParams();
const { error, successSubmit, clients } = useSelector(
(state) => state.clients
);
const [client, setClient] = useState(clients[0]);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getClients({ id: params.id }));
}, []);
const submitClient = () => {
dispatch(createClient(client));
};
return (
<div>{client.name} {clients[0].name}</div>
);
}
export default UpdateClient;
And the result is different client.name return test1,
while clients[0].name return correct data based on route parameter id (in this example parameter id value is 7) which is test7
I need the local state for temporary saving form data. I don't know .. why it's become different?
Can you please help me guys? Thanks in advance
You are referencing a stale state which is a copy of the clients state.
If you want to see an updated state you should use useEffect for that.
useEffect(() => {
setClient(clients[0]);
}, [clients]);
Notice that duplicating state is not recommended.
There should be a single “source of truth” for any data that changes in a React application.

React Hooks - function inside function component passed as prop can't access state

I have read about React hooks and wanted to try it on this new website I have been developing. I am trying to pass an async function as a prop. Part of the function is to set my "cities" state and console log just to see if the API works. I have been receiving "setCities is not a function" error or, cities returns undefined if I just console log it directly. I think the function can't access the {cities, setCities} state. I have tried it in class component and it works. Has anyone encountered similar situations? Below is the code sample:
import React, { useState } from "react";
import axios from "axios";
import Menu from "./Menu";
function App() {
const { cities, setCities } = useState([]);
const searchSubmit = async term => {
try {
const res = await axios.get("http://localhost:8080/general/search", {
params: { city: term }
});
setCities(res.data);
console.log(cities);
} catch (err) {
console.log(err.message);
}
};
return (
<div className="ui container">
<Menu handleSearchSubmit={searchSubmit} />
</div>
);
}
useStates return an array, not an object...
So you can change
const { cities, setCities } = useState([]);
to
const [ cities, setCities ] = useState([]);
And it should work.

Resources