Laravel/React - Getting an array of data from controller to react component - arrays

My case:
I am combining Laravel (laravel/ui scaffolding) and React App.
This is my first time trying this, and found myself stuck in getting data from BE to FE.
I Looks like I am getting the data, but my array of $testData is converted into a string When being logged from the Dataset of that element. I am not sure what I should do to have my array back to a json format instead.
the code:
A Controller sending my data:
public function index()
{
$testData = [
["name" => "Lucy"],
["name" => "Kurt"],
["name" => "Emma"],
];
return view('intern.index')->with('testData', $testData);
}
I have my blade, loading a div with a certain id:
#extends('layouts.app')
#section('body')
<div id="react-app" data-list={{ json_encode($testData) }} ></div>
#endsection
And my react component app.js that is rendered on the blade view:
function App( props ) {
console.log(props.list)
return (
<div className="container">
Hello World!
</div>
);
}
export default App;
if (document.getElementById('react-app')) {
const thisElement = document.getElementById('react-app');
let props = Object.assign({}, thisElement.dataset);
console.log(props)
/* The restult I am getting from that log:
{
list: "{{\"name\":\"Lucy\"},{\"name\":\"Kurt\"},{\"name\":\"Emma\"}}"
}
*/
ReactDOM.render(<App list={props.list} />, thisElement);
}

Update:
The solution was to simply parse the result back.
if (document.getElementById('react-app')) {
const thisElement = document.getElementById('react-app');
let props = Object.assign({}, thisElement.dataset);
console.log(props)
/* The restult I am getting from that log:
{
list: "{{\"name\":\"Lucy\"},{\"name\":\"Kurt\"},{\"name\":\"Emma\"}}"
}
*/
ReactDOM.render(<App list={JSON.parse(props.list)} />, thisElement);
}

Related

I am not getting data of my useState through .map function in React Js

React Js
I am trying to display data through .map which is in react state object, but I am not getting data on browser with any error, yes I now that I am not write setState in this code because i want only display my data on my browser. if this problem will be solved then I will done my setState, I Think setState is not necessary for only showing data which is in State Object.
import React from 'react';
import TinderCard from 'react-tinder-card';
function TinderCards(){
const [people, setPeople] = React.useState([
{
name: 'steve jobs',
url: 'https://cdn.britannica.com/04/171104-050-AEFE3141/Steve-Jobs-iPhone-2010.jpg'
},
{
name: 'mark zukerberg',
url: 'https://cdn.britannica.com/54/187354-050-BE0530AF/Mark-Zuckerberg.jpg'
}
]);
return (
<div>
{
people.map(person =>{
<h1>{person.name}</h1>
})
}
</div>
)
// const people = [] same thing
// BAD
// const people = [];
// people.push('sonny', 'qazi')
// GOOD (push to an array in REACT)
// setPeople([...people, 'mathan', 'lal'])
}
export default TinderCards;
You don’t return anything from map.
Change your return section to this:
return (
<div>
{people.map(person => (
<h1>{person.name}</h1>
))}
</div>
)
or if you like to keep the curly brackets syntax:
return (
<div>
{people.map(person => {
return <h1>{person.name}</h1>
})}
</div>
)

Cannot return the content from a nested array in React JS

I am trying to display the data I fetched from an API which is a nested array. The json file looks like this for one pool and the devices inside that pool:
[
{
"id": "staging",
"pool": "some name",
"status": "FAILED",
"deviceMonitoringEntries": [
{
"deviceDescriptor":{
"id": "Apple_TV_HD1",
}
]
}
]
I want to display the id of the pool first and then display the devices assigned to the pool by displaying the id in deviceDescriptor.
My code is like this:
import React, { useEffect, useState } from 'react'
import axios from 'axios'
function Pool(){
const url = 'http://localhost:8043/pools'
const [pool, setPool] = useState(null)
let content = null
useEffect(() => {
axios.get(url)
.then(response =>{
setPool(response.data)
})
}, [url])
if(pool){
console.log("in if pool")
console.log(pool)
return (
content=
<>
{pool.map((id) => {
<h3 key = {id}>{id}</h3>
return (
<>{pool.map(({ deviceMonitoringEntries}) => (
deviceMonitoringEntries.map((deviceDescriptor) => (
<p key = {deviceDescriptor.id}> {deviceDescriptor.id}</p>
))
))}</>
);
})}
</>
)
}
return(
<div>
{content}
</div>
)
}
export default Pool
However, the header <h3 key = {id}>{id}</h3> never prints. I can display the header and paragraph separately but it does not work together. I am very new to React and I would appreciate your help!
As per React documentation
React components implement a render() method that takes input data and returns what to display.
In the functional component, you directly add a return statement at the end.
You cannot assign variables like this in your code.
return (
content=
<>
...
</>
You got the response and you stored that value in a state variable. Use the variable and render your content in the final return statement.
{
pool.map((p) => (
<>
<h3 key={p.id}>{p.id}</h3>
{p.deviceMonitoringEntries.map((device) => (
<p key={device?.deviceDescriptor?.id}>{device.deviceDescriptor?.id}</p>
))}
</>
));
}
You can try like that in your code and I am attaching a sandbox for reference here.

Firebase call inside useEffect is not returning data properly

I have a component Photo.js responsible for making a call to to my firestore and rendering the returned data. The returned data is set to a state variable venues.
This data is then mapped over and rendered to the browser, however I'm getting the following error in the browser:
Cannot read properties of null (reading 'map')
And when I console log the state variable venues, it's being returned as null.
If I comment out the code responsible for mapping out the returned data (below), my webpage renders without problem - and if I uncomment the same code and save, the firebase call works and the data is rendered:
{venues.map((item) => {
return(<img src = {item.photoUrl}/>)
})}
Here's the Photos component controlling the firebase call:
import { useState,useEffect } from 'react'
import {getVenues} from '../../services/firebase.js'
const Photo = () => {
const [ venues,setVenues ] = useState(null)
useEffect(() => {
console.log('it got here')
async function getAllVenues(){
const response = await getVenues()
await setVenues(response)
}
getAllVenues()
},[])
console.log(venues)
return(
<div className = 'venueCard-container'>
{venues.map((item) => {
return(<img src = {item.photoUrl}/>)
})}
</div>
)
}
export default Photo
...and the the firebase functions in services/firebase.jss
import {firebase} from '../firebaseConfig'
export async function getVenues() {
const response = await firebase
.firestore()
.collection('venues')
.get()
return response.docs
.map((venue) => ({...venue.data()}))
}
I'm thinking this is some sort of async problem - the component is rendering before the firebase call has returned the data. Suggestions?
const [ venues,setVenues ] = useState(null)
You've set the initial value of the state to be null, so that's what it will be on the first render. Some time later the data will finish loading and you'll render again, but until that time, your component needs to work with the initial state. You could check for null and render nothing:
return(
<div className = 'venueCard-container'>
{venues && venues.map((item) => {
return(<img src = {item.photoUrl}/>)
})}
</div>
)
...or you could render a placeholder:
if (!venues) {
return <div>Loading...</div>
} else {
return (
<div className = 'venueCard-container'>
{venues.map((item) => {
return(<img src = {item.photoUrl}/>)
})}
</div>
)
);
}
...or you could make the initial state be an empty array, which means it will always have a .map method even before loading has finished:
const [ venues,setVenues ] = useState([])

List all items in an array in ReactJS

This is the file that I'm rendering in App.js:
ProductList.js
import React from 'react'
export default function ProductList() {
var items = JSON.parse(localStorage.getItem("products")); //[foo: "4.43", bar: "3.25"]
const listitems = () => {
for( var p in items) {
<p>{p}, {items[p]}</p>
}
}
return (
<div>
{listitems}
</div>
);
}
This does not output anthing.
The question is: how do I list all the items in an array like "foo, 4.43"...?
return (
{items.map((el) => (
<p>{el}</p>
)}
)
I guess there are a few issues with this code.
First, the products you are getting from localStorage is an array, so you won't be able to get the key:value pair of it.
You would be better off transforming the products into an object, like:
{
foo: "4.43",
bar: "3.25"
}
Then, one alternative is to get the keys by doing const productKeys = Object.keys(products). Then map through them and display the values as well:
const listItems = productKeys.map(key => <p>{key}: {products[key]}</p>)
return {
<div>
{listItems}
</div>
}

JSON data from firebase using object.entries

imageThe images shows my data stored in Firebase,it is a Json data.
Error is type Error: Cannot read property 'date' of undefined,
what I am doing wrong???
I want to access date from it, on clicking button show_data , date should be returned,but on the user screen.
I am unable to print it on console and user screen
import React, { Component } from "react"; //, { useState }
import "./styles.css";
import axios from "axios";
class App extends Component {
state = {
getData: "Date"
};
reloadHandler = () => {
axios.get("https://loco-97cba.firebaseio.com/.json").then((res) => {
const arrayObj = Object.entries(res.data).map((e) => [e[0]]);
const arrayObj1 = Object.entries(res.data).map((e) => [e[1]]);
console.log(arrayObj);
console.log(arrayObj1);
this.setState({
getData: arrayObj1[1].date
});
console.log( "date", this.state.getData)
// }
});
};
render() {
return (
<div className="App">
<button
onClick={() => {
this.reloadHandler();
}}
>
GET_DATA
</button>
<br/>
<br/>
<div style={{border:"black 1px solid",height:"100px"}} >{this.state.getData}</div>
</div>
);
}
}
export default App;
Below statement will not log your dates into the console. Because setState will take time to actually reflects the values.
console.log( "date", this.state.getData)
Instead what you can do is move that console.log into the render method so you can see the updated values each time.
One more thing you are not able to see the result on the webpage because your state this.state.getData is an array.
<div style={{border:"black 1px solid",height:"100px"}} >{this.state.getData}</div>
If you want to keep it as an array then you can map over it and print the data like this.
{this.state && this.state.getData.map(date => <div style={{border:"black 1px solid",height:"100px"}} >{date}</div>)}
Otherwise, just try this -
<div style={{border:"black 1px solid",height:"100px"}} >{this.state.getData[0]}</div>
See this -
Why is setState in reactjs Async instead of Sync?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries

Resources