I am using ReactJs with Laravel as an API. I Want to display some data but nothing worked for me.
This is the result of the API:
{
"user_id": 2,
"id": 1,
"chat": [
{
"sender_id": 3,
"message": "Hi"
},
{
"sender_id": 4,
"message": "Hello"
}
]
}
When I try to display user_id, it displayed it but the other part, the chat, didn't show up.
This is how I consume the API:
const [chatsData, setChats] = useState([]);
// ** Renders Chat
useEffect(() => {
getChats()
}, []);
const getChats = async () => {
const response = await axios.get(`${API_ENDPOINT}/api/listChats`);
setChats(response.data);
}
<ul className='chat-users-list chat-list media-list'>
{chatsData.map((item) => {
return (
<>
<Avatar img={item?.senders?.user_image} imgHeight='42' imgWidth='42' />
<li><h5>{item.chat?.message}</h5></li>
</>
)
})}
</ul>
I will be very thankful if anyone could help me.
You just have to loop on the chat field like:
import React from 'react';
export default function App() {
const response = {
user_id: 2,
id: 1,
chat: [
{
sender_id: 3,
message: 'Hi',
},
{
sender_id: 4,
message: 'Hello',
},
],
};
return (
<div>
<ul className="chat-users-list chat-list media-list">
{response.chat?.map((item) => {
return (
<>
<li>
<h5>
{item.sender_id} : {item?.message}
</h5>
</li>
</>
);
})}
</ul>
</div>
);
}
Code example here
Related
I am deveoping a Kanban Board. I use ReactJS to call the backend for stages and tasks that are open in each stage. It is a very simple JSON that I get from the backend.
JSON
[
{
"open_tasks": [
{
"task_id": 37,
"task_title": "Develop frontend"
},
{
"task_id": 38,
"task_title": "Create app"
}
],
"stage_id": 6,
"stage_title": "Tasks"
},
{
"open_tasks": [],
"stage_id": 15,
"stage_title": "Blocked"
},
{
"open_tasks": [],
"stage_id": 18,
"stage_title": "Finished"
}
]
Now I want to use ReactJS to print the nested JSON, however I cannot use map inside a map.
import { useEffect, useState } from "react";
export function IndexKanbanBoard() {
const [stagesWithOpenTasks, setStagesWithOpenTasks] = useState(() => []);
// Load stages
const loadStagesWithOpenTasksForBoard = async (e) => {
let result = await fetch("https://localhost:5002/api/kanban_boards/get_stages_with_open_tasks_for_board", {
method: "GET",
headers: {
'Authorization': 'Bearer ' + 'bla bla'
}
});
let resultJson = await result.json();
if (result.status === 200) {
setStagesWithOpenTasks(resultJson.map(fetch_object => {
return fetch_object
}))
}
};
// On load
useEffect(() => {
loadStagesWithOpenTasksForBoard()
}, []);
return (
<div>
{stagesWithOpenTasks.map((item, index) => (
<div key={index}>
<h2>{item.stage_title}</h2>
<p>I WANT TO SHOW open_tasks HERE</p>
</div>
))}
</div>
);
}
export default IndexKanbanBoard;
How can i loop trough nested JSON in ReactJS?
Assigning the next array items to a variable will help please have a look
return (
<div>
{data.map((item, index) => {
const openTasks = item["open_tasks"];
return (
<div key={index}>
<h2>{item.stage_title}</h2>
{openTasks.map((item) => (
<p>{item.task_title}</p>
))}
<p></p>
</div>
);
})}
</div>
);
import React, { useEffect, useState } from 'react';
import Axios from 'axios';
const PictureOfTheDay = () => {
const [fetchedImage, setFetchedImage] = useState('');
const imageHandler = (name) => {
Axios.get(`https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos?earth_data=2015-6-3&sol=1000&camera${name}&api_key="MY_API_KEY"/`).then((res) => {
setFetchedImage(res.data.photos[0].img_src);
// console.log(res.data.photos.img_src);
}, []);
};
useEffect(() => {
imageHandler();
});
return (
<section>
<h3>Astronomy Picture Of The Day</h3>
<div className="picture">
<button onClick={() => imageHandler('FHAZ')}>FHAZ</button>
<button onClick={() => imageHandler('RHAZ')}>RHAZ</button>
<button onClick={() => imageHandler('MAST')}>MAST</button>
<button onClick={() => imageHandler('CHEMCAM')}>CHEMCAM</button>
</div>
<img src={fetchedImage} alt="" />
</section>
);
};
export default PictureOfTheDay;
Currently, I am doing something like this but it is just showing me one image I know I have done something stupid but please help me out.
Used dummy API.
https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos?sol=1000&api_key=DEMO_KEY
The JSON response sample.
{
"id": 102693,
"sol": 1000,
"camera": {
"id": 20,
"name": "FHAZ",
"rover_id": 5,
"full_name": "Front Hazard Avoidance Camera"
},
"img_src": "http://mars.jpl.nasa.gov/msl-raw-images/proj/msl/redops/ods/surface/sol/01000/opgs/edr/fcam/FLB_486265257EDR_F0481570FHAZ00323M_.JPG",
"earth_date": "2015-05-30",
"rover": {
"id": 5,
"name": "Curiosity",
"landing_date": "2012-08-06",
"launch_date": "2011-11-26",
"status": "active"
}
},
{
"id": 102694,
"sol": 1000,
...
"img_src": "http://mars.jpl.nasa.gov/msl-raw-images/proj/msl/redops/ods/surface/sol/01000/opgs/edr/fcam/FRB_486265257EDR_F0481570FHAZ00323M_.JPG",
}
},
...
Store the data in a useState variable and then map it and show only the image URL[img_src]. Hope it will solve your problem in this way.
const [myData, setMyData] = useState([]);
useEffect(() => {
fetch("API...")
.then(res=>res.json())
.then(data=>setMyData(data));
}, [])
{
myData.map(myData =><ImageCompo
key={myData.id}
myData={myData}
></ImageCompo>)
}
In ImageCompo retrieve imag_src props:
function ImageCompo({myData}) {
const{id,img_src}=myData;
<img src={img_src} alt='' width={200} height={200}></img>
Hope it would help you.
I'm trying to get specific values from an array object returned by my node.js api
Here's the array of object returned by my node.js api
[
{
"name": "device1",
"serial": "WMD105222022",
"status": "online"
},
{
"name": "device2q",
"serial": "sdfsdf",
"status": "online"
},
{
"name": "ducs",
"serial": "WMD105222022",
"status": "online"
}
]
Here's my react.js code
import React, {useState, useEffect} from "react";
import './Module.css';
import {SDH} from '../../components';
import {temp, water, humidity, nutrient} from '../../assets';
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
import Form from 'react-bootstrap/Form';
import {Link} from 'react-router-dom';
import Axios from "axios";
const Module = () => {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
const email = sessionStorage.getItem("email");
const [device, setDevice] = useState({});
Axios.defaults.withCredentials = true;
useEffect(() => {
Axios.get("http://localhost:3020/getdevice", {
params: {
email: email
}
})
.then((response) => {
setDevice(response.data);
})
// .then((response) => {},
// (err) => {
// alert("No Data To Show");
// }
// )
.catch((err) => {
return false;
});
},[]);
const DisplayData = () => {
return (
<div>
<td>{device.name}</td>
<td>{device.serial}</td>
<td>{device.status}</td>
</div>
);
};
return (
<div className="MainBodyM">
<SDH/>
<h3 className="deviceStatus"></h3>
{/* <Button onClick={getDevices} variant="primary" type="submit">Refresh List</Button> */}
<div className="tempHeader">
<table>
<tr>
<td>Name</td>
<td>Serial Number</td>
<td>Status</td>
</tr>
<tr>
{DisplayData}
</tr>
</table>
</div>
<Link to="/registerdevice">
<Button>Add Control Module</Button>
</Link>
</div>
);
};
export default Module;
I needed to get the name, serial, and status to be displayed in a table. up until now i'm still getting nowhere, please help, i'm only using {JSON.stringify(device, null, 3)} to display the returned array of object that's why i know i'm getting an array of object. I'm open to suggestions and correction. Thank you.
I need the output to be like this, regardless how many devices/data i add in array of object.
Device Serial Status
Device1 121 online
device2 234135 offline
balcony ash3 online
bathroom dsgfkahaskj23 online
so on... tj2l5 offline
You must send an array from the backend. You must send a JSON
In express
app.get("/test", (req, res) => {
res.json({
array: [
{
name: "device1",
serial: "WMD105222022",
status: "online",
},
{
name: "device2q",
serial: "sdfsdf",
status: "online",
},
{
name: "ducs",
serial: "WMD105222022",
status: "online",
},
],
});
});
Note that I send a JSON, not an array
In React:
const [data, setData] = useState([]);
useEffect(() => {
var config = {
method: "get",
url: "http://localhost:3000/test",
headers: {},
};
axios(config)
.then(function (response) {
const data = JSON.stringify(response.data);
const array = JSON.parse(data).array;
setData(array);
})
.catch(function (error) {
console.log(error);
});
}, []);
Note that I convert the JSON to an object to be able to iterate it
the return on the component
<table>
{data &&
data.map((row, key) => {
return (
<tr key={key} style={{ color: "red" }}>
<td>{row.name}</td>
<td>{row.serial}</td>
<td>{row.status}</td>
</tr>
);
})}
</table>
You can extract the columns name, ie. "Device", "Serial", "Status", into an array, and iterate over them using map function:
const [data, setDate] = useState();
const columns = ["Device", "Serial", "Status"]; // hard code the columns
const lookUpDataKey = {
Device: "name",
Serial: "serial",
Status: "status"
};
useEffect(() => {
setDate(dataFromApi); // mimic getting data from api
}, []);
if (!data) return <div>loading</div>;
return (
<div className="App">
<div style={{ display: "flex" }}>
{columns.map((column, columnIndex) => (
<div key={columnIndex}>
{/* Column name */}
<div>{columns[columnIndex]}</div>
{/* Column data */}
{data.map((item, dataIndex) => (
<div key={dataIndex}>
<div>{item[lookUpDataKey[column]]}</div>
</div>
))}
</div>
))}
</div>
</div>
);
Notice we use a lookUpDataKey object for matching column's name to the corresponding object key.
Try it out in updated sandbox.
How can i filter some products by categories using firebase? This is a fragment of my code
Not sure if you have a correct db.json file, i had to flatMap the result but here is a working code. I used require to load you json file and left const [products, setProducts] = useState([]); just in case. Also i switched categories to useMemo so this variable will not update on each re-render.
import React, { useState, useEffect, useMemo } from "react";
import "./styles.scss";
import { Link } from "react-router-dom";
const dbProducs = require("./db.json");
const CategoriesPage = () => {
// const {product} = useContext(Context)
const [products, setProducts] = useState([]);
const categories = useMemo(() => {
return [
{ id: 1, title: "Tablets" },
{ id: 2, title: "Computers" },
{ id: 3, title: "Consoles" },
{ id: 4, title: "Photo and video" },
{ id: 5, title: "Technics" },
{ id: 6, title: "Game Content" },
{ id: 7, title: "Notebooks" },
{ id: 8, title: "Smartphones" },
{ id: 9, title: "Headphones" },
{ id: 10, title: "Steam" }
// {id: 11,imageSrc:steamcards, title: 'Стиральные машины'},
// {id: 12,imageSrc: coffeemaschine, title: 'One stars'},
// {id: 13,imageSrc:headphones, title: 'Холодильники'},
];
}, []);
useEffect(() => {
const flatMapped = dbProducs.flatMap((x) => x.products);
setProducts(flatMapped);
}, []);
return (
<section className="popular__categories">
<h3 className="events__title">
<span>Categories</span>
</h3>
<div className="categories__wrapper">
{categories.map((category) => (
<Link
to={`${category.id}`}
className="categories__content"
key={category.id}
>
<h2 className="categories__title">{category.title}</h2>
<img
className="categories__img"
alt={category.title}
src={category.imageSrc}
/>
<ul>
{products
.filter((p) => p.category === category.title)
.map((p) => (
<li key={p.id}>{p.name}</li>
))}
</ul>
</Link>
))}
</div>
</section>
);
};
export default CategoriesPage;
Technically it would be better to clone and extend your categories objects with additional array property with useMemo, or you can add additional Map object with key = Category(title) and value = products (filtered) but it is up to you.
Full example with Context, Routes, Navigation:
I have the following nextJS app:
export default function Home({ productsData }) {
const [user, setUser] = useState(null);
const [products, setProducts] = useState([]);
useEffect(() => {
if (productsData) setProducts(productsData);
}, [productsData]);
useEffect(() => {
const userLocal = window.localStorage.getItem("user");
if (userLocal) {
setUser(JSON.parse(userLocal));
}
}, []);
return (
<div className="container">
<ul className="row">
{products.map((product) => {
return (
<h1>
{product.translation.name} -{" "}
{user
? user.premium
? product.prices.premium
: product.prices.price
: product.prices.price}
</h1>
);
})}
</ul>
</div>
);
}
export async function getServerSideProps() {
const data = [
{
prices: {
premium: 25,
price: 59.95,
},
translation: {
name: "Product 1",
},
},
{
prices: {
premium: 25,
price: 29.95,
},
translation: {
name: "Product 2",
},
},
];
return {
props: {
productsData: data,
},
};
}
This works but if I do a "curl" request to localhost I dont see that the server is rendering anything, that is because useEffect setting "products" happen on the Client side.
But if I do this:
const [products, setProducts] = useState(productsData);
Then I have this error:
Error: Hydration failed because the initial UI does not match what was rendered on the server. - Buscar con Google
So, do I have to choose between SSR and having the state in the client side?
I tried const [products, setProducts] = useState(productsData);
you dont need useEffect this time !
you can use Loading for this
export default function Home({ productsData }) {
const [user, setUser] = useState(null);
useEffect(() => {
const userLocal = window.localStorage.getItem("user");
if (userLocal) {
setUser(JSON.parse(userLocal));
}
}, []);
return (
<div className="container">
<ul className="row">
{productsData?.map((product) => {
return (
<h1>
{product.translation.name} -{" "}
{user
? user.premium
? product.prices.premium
: product.prices.price
: product.prices.price}
</h1>
);
})}
</ul>
</div>
);
}
export async function getServerSideProps() {
const data = [
{
prices: {
premium: 25,
price: 59.95,
},
translation: {
name: "Product 1",
},
},
{
prices: {
premium: 25,
price: 29.95,
},
translation: {
name: "Product 2",
},
},
];
return {
props: {
productsData: data,
},
};
}
I strongly recommend TanStack Query (formerly ReactQuery) for this kind of scenario.
You can take advantage of SSR, client fetching, etc. TanStack Query is just a cache layer between NextJS and your data.
They have a SSR guide with NextJS in their docs.