How to use json data for react-select? - reactjs

How can I use a json data from a .json file and use it as options of react-select?
Currently I am using some options from the example they have in the documentation.
Here is my jsx code -
import React, { useEffect } from "react";
import Button from "#ui/button";
import Select from "react-select";
import { useState } from "react";
const options = [
{ value: "chocolate", label: "Chocolate" },
{ value: "strawberry", label: "Strawberry" },
{ value: "vanilla", label: "Vanilla" },
];
function Company({}) {
const [selectedOption, setSelectedOption] = useState(null);
return (
<>
<form className="company-form">
<div className="p-3 pt-0">
<label className="mt-3" htmlFor="jurisdiction-code">
Company Jurisdiction
</label>
<Select
className="text-xl"
defaultValue={selectedOption}
onChange={setSelectedOption}
options={options}
required
isClearable={true}
id="jurisdiction-code"
/>
</div>
<div className="mt-5">
<Button size="medium" fullwidth>
Submit
</Button>
</div>
</form>
</>
);
}
export default Company;
I have a separate json file for the options.
Here is my jurisdiction.json file code -
[
{
"id": 1,
"jurisdiction": "Alabama (US)",
"code": "us_al"
},
{
"id": 2,
"jurisdiction": "Alaska (US)",
"code": "us_ak"
},
{
"id": 3,
"jurisdiction": "Arizona (US)",
"code": "us_az"
},
{
"id": 4,
"jurisdiction": "Arkansas (US)",
"code": "us_ar"
},
{
"id": 5,
"jurisdiction": "California (US)",
"code": "us_ca"
}
]
I want to display jurisdiction and use code as the value.
How can I do that?

If the JSON data file is located in the public directory then you can use a useEffect hook to issue a fetch to retrieve it and save it into local state.
Example:
Assuming JSON file is located in public/data/data.json
function Company() {
const [selectedOption, setSelectedOption] = useState();
const [options, setOptions] = useState([]);
useEffect(() => {
const getOptions = async () => {
try {
const response = await fetch("/data/data.json");
const options = await response.json();
console.log(options);
setOptions(
options.map(({ id, jurisdiction, code }) => ({
id,
label: jurisdiction,
value: code
}))
);
} catch (error) {
// ignore
}
};
getOptions();
}, []);
return (....);
}

Related

React rest call map result to selectbox with avatar and label per option

Hi here is rest response:
[
{
"self": "https://your-domain.atlassian.net/rest/api/3/project/EX",
"id": "10000",
"key": "EX",
"name": "Example",
"avatarUrls": {
"48x48": "https://your-domain.atlassian.net/secure/projectavatar?size=large&pid=10000",
"24x24": "https://your-domain.atlassian.net/secure/projectavatar?size=small&pid=10000",
"16x16": "https://your-domain.atlassian.net/secure/projectavatar?size=xsmall&pid=10000",
"32x32": "https://your-domain.atlassian.net/secure/projectavatar?size=medium&pid=10000"
},
"projectCategory": {
"self": "https://your-domain.atlassian.net/rest/api/3/projectCategory/10000",
"id": "10000",
"name": "FIRST",
"description": "First Project Category"
},
"simplified": false,
"style": "classic",
"insight": {
"totalIssueCount": 100,
"lastIssueUpdateTime": "2022-12-08T07:09:19.702+0000"
}
},
{
"self": "https://your-domain.atlassian.net/rest/api/3/project/ABC",
"id": "10001",
"key": "ABC",
"name": "Alphabetical",
"avatarUrls": {
"48x48": "https://your-domain.atlassian.net/secure/projectavatar?size=large&pid=10001",
"24x24": "https://your-domain.atlassian.net/secure/projectavatar?size=small&pid=10001",
"16x16": "https://your-domain.atlassian.net/secure/projectavatar?size=xsmall&pid=10001",
"32x32": "https://your-domain.atlassian.net/secure/projectavatar?size=medium&pid=10001"
},
"projectCategory": {
"self": "https://your-domain.atlassian.net/rest/api/3/projectCategory/10000",
"id": "10000",
"name": "FIRST",
"description": "First Project Category"
},
"simplified": false,
"style": "classic",
"insight": {
"totalIssueCount": 100,
"lastIssueUpdateTime": "2022-12-08T07:09:19.702+0000"
}
}
]
I want to make select bobx having
<option value={data.id}><Img {data.16x16}/>data.label</option>
But result would be all projects if company has multiple projects so select box values have to map or loop into react
<Select options="result">
Im stuck as my code displays only label not any image there.
Another problem is that using data.avatarUrls.16x16 does not compile. VSCode says expecting "," and puts red underline to 16x16
Here is my code a lot is broken here because I have tested a lot ways but no luck
import React, { useState } from 'react';
import Select from 'react-select'
import { components } from 'react-select';
//Kun selectbox
const handleChange = event => {
//console.log(event.target.value);
setSelected(event.target.value);
};
//Palauttaa projectit json taulukon
const getProjects = async () => {
//Matti tähän sitten atlasion cmpany projection haku
const response = await api.asUser().requestJira(route`/rest/api/3/project`, {
headers: {
'Accept': 'application/json'
}
});
const data = await response.json();
//Mapataa hausta tarvittavat tiedot
const result = data.map(function (item, i) {
console.log('test');
return [
{
label: item.name,
value: item.id,
avatar: item.avatarUrls.16x16
}
]
})
return result
}
function Projects() {
//haetaan atlasiansita projectit array
const p = getProjects
//asetetaan state selectbox muutokselle
const [selected, setSelected] = useState(p.id);
return (
<div className='projects'>
<Select
className='select-projects'
options={p}
onChange={handleChange}
/>
</div>
);
}
export default Projects

How to Display data of single json file in mulitple tables through repeating a single react component

I am a beginner in ReactJS.
What I want is, I have a Component Datatable.js and I want to create three tables in that component by configuring data of a single JSON File and there should be only one component for three tables but the condition is the values in tables must come different-different in each table like- in first tables- Name, email, number; in the second table- email, city, number and in the third table- Name, Profession, number, city. I want to perform all that operation by repeating Datatable.js component three times in App.js so that three tables render, not by writing table element three times in Datatable.js.
So please tell me how to do that.
I have got the JSON values in the data state and I know it can be displayed through the map() method but the problem is how to send these JSON file values in each repeating component and how Datatable.js would get it so that values would appear differently in each table as I mentioned above?
data.json:
[
{
"person": {
"name": "Viswas Jha",
"avatar": "images/profile.jpg"
},
"city": "Mumbai",
"email": "vishwasjha#gmail.com",
"number": 123456,
"profession": "UI Designer"
},
{
"person": {
"name": "Damini Pandit",
"avatar": "images/profile.jpg"
},
"city": "Delhi",
"email": "daminipandit#gmail.com",
"number": 1345645,
"profession": "Front-end Developer"
},
{
"person": {
"name": "Nihal Lingesh",
"avatar": "images/profile.jpg"
},
"city": "Delhi",
"email": "nihallingesh#gmail.com",
"number": 12345689,
"profession": "UX Designer"
},
{
"person": {
"name": "Akash Singh",
"avatar": "images/profile.jpg"
},
"city": "Kolkata",
"email": "akashsingh#gmail.com",
"number": 1234566,
"profession": "Backend Developer"
}
]
App.js:
import Datatable from './Datatable';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import {useState, useEffect} from 'react';
import './App.css';
const fetchData = new Promise((myResolve, myReject) => {
let req = new XMLHttpRequest();
req.open('GET', "./data.json");
req.onload = function() {
if (req.status == 200) {
return myResolve(req.response);
} else {
return myReject("File not Found");
}
};
req.send();
});
function App() {
const [data, setData] = useState([]);
useEffect(() => {
fetchData.then((jsonData) => setData(JSON.parse(jsonData)));
}, []);
return (
<>
<Datatable Data = {data} />;
<Datatable Data= {data}/>;
<Datatable Data= {data}/>;
</>
);
}
export default App;
Datatable.js:
import React from 'react';
import Grid from '#material-ui/core/Grid';
export default function Datatable({Data}) {
return (
<div className='main text-center '>
<h1 className='head py-3'>Datatable</h1>
<Grid container spacing={1} className='contain m-auto mt-5 ps-5 pb-4'>
<table className="table table-striped">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Number</th>
</tr>
</thead>
<tbody>
{
Data.map((elem, ind)=>{
return (
<tr key={ind}>
<td className='d-flex justify-content-between align-items-center'>
<img src={elem.person.avatar} alt="avatar"/>
{elem.person.name}</td>
<td>{elem.email}</td>
<td>{elem.number}</td>
</tr>
)
})
}
</tbody>
</table>
</Grid>
</div>
);
}
Update your code with this.
App.js
import Datatable from './Datatable';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import { useState, useEffect } from 'react';
import './App.css';
const fetchData = new Promise((myResolve, myReject) => {
let req = new XMLHttpRequest();
req.open('GET', "./data.json");
req.onload = function () {
if (req.status == 200) {
return myResolve(req.response);
} else {
return myReject("File not Found");
}
};
req.send();
});
function App() {
const [sortReverse,setSortReverse] = useState(false)
const [data, setData] = useState({
tableOne: [],
tableTwo: [],
tableThree: [],
});
useEffect(() => {
fetchData.then(function (jsonData) {
const tableOne = jsonData?.map(
({ person: { name }, email, number }) => ({
name,
email,
number,
})
);
const tableTwo = jsonData?.map(({ city, email, number }) => ({
city,
email,
number,
}));
const tableThree = jsonData?.map(
({ person: { name }, email, number, city }) => ({
name,
email,
number,
city,
})
);
setData({
tableOne: tableOne,
tableTwo: tableTwo,
tableThree: tableThree,
});
});
}, []);
const handleSort = (e) => {
const sortedArrTableOne = data?.tableOne?.sort((a, b) => {
return sortReverse
? a[e.toLowerCase()]?.localeCompare(b[e.toLowerCase()])
: b[e.toLowerCase()]?.localeCompare(a[e.toLowerCase()]);
});
const sortedArrTableTwo = data?.tableTwo?.sort((a, b) => {
return sortReverse
? a[e.toLowerCase()]?.localeCompare(b[e.toLowerCase()])
: b[e.toLowerCase()]?.localeCompare(a[e.toLowerCase()]);
});
const sortedArrTableThree = data?.tableThree?.sort((a, b) => {
return sortReverse
? a[e.toLowerCase()]?.localeCompare(b[e.toLowerCase()])
: b[e.toLowerCase()]?.localeCompare(a[e.toLowerCase()]);
});
setData((prevState) => ({
...prevState,
tableOne: sortedArrTableOne,
tableTwo: sortedArrTableTwo,
tableThree: sortedArrTableThree,
}));
setSortReverse(!sortReverse)}
const tableOneColumns = [
{ name: "Name", accessor: "name" },
{ name: "Email", accessor: "email" },
{ name: "Number", accessor: "number" },
];
const tableTwoColumns = [
{ name: "Email", accessor: "email" },
{ name: "City", accessor: "city" },
{ name: "Number", accessor: "number" },
];
const tableThreeColumns = [
{ name: "Name", accessor: "name" },
{ name: "Email", accessor: "email" },
{ name: "Number", accessor: "number" },
{ name: "City", accessor: "city" },
];
return (
<>
<Datatable data={data?.tableOne} columns={tableOneColumns} handleSort={handleSort}/>
<Datatable data={data?.tableTwo} columns={tableTwoColumns} handleSort={handleSort}/>
<Datatable data={data?.tableThree} columns={tableThreeColumns} handleSort={handleSort}/>
</>
);
}
export default App;
DataTable.js
import React from "react";
import Grid from "#material-ui/core/Grid";
import { Box } from "#material-ui/core";
export default function Datatable(props) {
const { data = [], columns = [], handleSort } = props;
return (
<Box className="main text-center ">
<h1 className="head py-3">Datatable</h1>
<Grid container spacing={1} className="contain m-auto mt-5 ps-5 pb-4">
<table className="table table-striped ">
<thead>
<tr>
{columns?.map((column, index) => (
<th key={index} scope="col" onClick={()=> handleSort(column?.name)}>
{column?.name}
</th>
))}
</tr>
</thead>
<tbody>
{data.map((elem, ind) => {
return (
<tr key={ind}>
{columns?.map((column) => {
return (
<td className="d-flex justify-content-between align-items-center">
{elem?.[column.accessor]}
</td>
);
})}
</tr>
);
})}
</tbody>
</table>
</Grid>
</Box>
);
}
Note: If you want to sort then click on heading Name or Email etc.

.map is not a function with MaterialUI Tab component

So I'm trying to populate a in-memory MirageJS' database with a post request of the data in useEffect, making a get request after. Then I save the result to columnsNames state and use it to map this array and read the information as a label of Tab MaterialUI component. However, I have some questions:
When I put a console.log after useEffect or inside get request, both response.data and columnsNames state have 2 identical arrays. Why 2 and not 1?
At runtime the console prints
Uncaught TypeError: columnsNames.map is not a function
The above error occurred in the <ScrollableTabsButtonAuto> component
and nothing is showed in the screen. Why?
Anyone that could help me, thanks in advance!
Data.ts
export const data = [
{
"id": 1,
"title": "Test 1",
"steps": [
"Read a starting book",
"Keep calm and drink coffee",
"Don't Panic so much",
]
},
{
"id": 2,
"title": "Test 2",
"steps": [
"Get some helpful help",
"Don't loose yourself",
]
},
{
"id": 3,
"title": "Test 3",
"steps": [
]
},
{
"id": 4,
"title": "Test 4",
"steps": [
]
},
{
"id": 5,
"title": "Test 5",
"steps": [
]
},
{
"id": 6,
"title": "Test 6",
"steps": [
]
}
]
App.tsx
import { createServer, Model } from 'miragejs';
createServer({
models: {
columns: Model,
},
routes() {
this.namespace = 'api'
this.get('columns', () => {
return this.schema.all('columns')
})
this.post('columns', (schema, request) => {
const data = JSON.parse(request.requestBody)
return schema.create('columns', data)
})
}
})
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
Tab.tsx
interface ColumnTypes {
id: number,
title: string,
steps: string[]
}
export default function ScrollableTabsButtonAuto() {
const [value, setValue] = React.useState(0);
const [columnsNames, setColumnsNames] = React.useState<ColumnTypes[]>([])
const handleChange = (event: React.SyntheticEvent, newValue: number) => {
setValue(newValue);
};
React.useEffect(() => {
api.post('columns', data)
.then( () => {
api.get<ColumnTypes[]>('columns')
.then(response => setColumnsNames(response.data))
})
}, [])
return (
<Box sx={{ maxWidth: { xs: 320, sm: 1280 }, bgcolor: 'background.paper' }}>
<Tabs
value={value}
onChange={handleChange}
variant="scrollable"
scrollButtons="auto"
aria-label="scrollable auto tabs example"
>
{columnsNames.map(({ id, title }) => (
<Tab
label={title}
key={id}
/>)
)}
</Tabs>
</Box>
);
}

React Apex Chart Data, Image and API

How to modify series and options, i want to make chart type=treemap on react hooks like this
i have name, user and percent on api.
{
"data": [
{
"id": "1",
"name": "Pisces",
"user": "95",
"percent": "3.15%",
},
{
"id": "2",
"name": "Leo",
"user": "50",
"percent": "2.35%",
},
{
"id": "3",
"name": "Capricorn",
"user": "91",
"percent": "3.12%",
}
]
}
and source for apex https://apexcharts.com/docs/chart-types/treemap-chart/
import React, { useState,useEffect } from 'react';
import axios from 'axios';
import './App.css';
import Chart from 'react-apexcharts'
import icUser from './image/profile-user.png'
import icChart from './image/pie-chart.png'
const App =()=> {
const [dataUser,setDataUser]=useState([])
useEffect(() => {
axios.get("http://localhost:4000/data")
.then(response =>{
setDataUser(response.data)
}).catch(e => {
alert(e);
})
}, [])
const series = {.....}
const options = {.....}
return (
<div>
<Chart options={options} series={series} height={350} type="treemap"/>
</div>
)
}
export default App
In series you need to pass an array like this, Where x is the name, and y percentage. and In option you can modify the treemap chart like change height, type, plotOptions and more...
const App = () => {
const [dataUser, setDataUser] = useState([])
useEffect(() => {
axios.get("http://localhost:4000/data")
.then(response => {
setDataUser(response.data)
}).catch(e => {
alert(e);
})
}, [])
const seriesData = [];
const options = {}
dataUser.map((val) => {
seriesData.push(
{
x: val.name, //
y: val.percent //
}
);
});
const series = [{ data: seriesData }];
return (
<div>
<Chart options={options} series={series} height={350} type="treemap" />
</div>
)
}
export default App

"TypeError: Cannot read property 'name' of undefined" when looping on JSON

I have a JSON like this :
{
"cards": [
{
"name": "aquaman",
"img": "aquaman.png"
},
{
"name": "batman",
"img": "batman.png"
},
{
"name": "captainamerica",
"img": "captainamerica.png"
},
{
"name": "deadpool",
"img": "deadpool.png"
},
{
"name": "flash",
"img": "flash.png"
},
{
"name": "greenlantern",
"img": "greenlantern.png"
},
{
"name": "ironman",
"img": "ironman.png"
},
{
"name": "spiderman",
"img": "spiderman.png"
},
{
"name": "ironfist",
"img": "ironfist.png"
},
{
"name": "thepunisher",
"img": "thepunisher.png"
},
{
"name": "wonderwoman",
"img": "wonderwoman.png"
},
{
"name": "xman",
"img": "xman.png"
}
]
}
and I want to loop on these objects and to render a div with a backgroundImage with the img property of every object,
I tried this, but it tells me:
TypeError: Cannot read property 'name' of undefined
import React, { useEffect, useState } from "react";
import cardsJson from "../../../utils/cards.json";
const [cards, setCards] = useState();
useEffect(() => {
setCards(cardsJson.cards);
}, [cards]);
{cards &&
cards.map((card: any, index: number) => (
<div key={card.name} className="cardHero">
<div className="front"></div>
<div
className="back"
style={{
backgroundImage: `url(${require(`../../../assets/images/${card.img}`)})`
}}
></div>
</div>
))}
It looks like inside the map I can't get name or img for every card ?? And when I console log "cards", it show me the JSON like above with name and img properties
Assuming your code is wrapped in a function component (see below), it may be an issue with how you're importing / using cards.json. Also in the useEffect, make the dependency array [] instead of [cards]. I changed your code to this and it works:
import React, { useEffect, useState } from "react";
import cardsJson from "./cards.json";
export function Cards() {
const [cards, setCards] = useState();
useEffect(() => {
console.log(cardsJson);
setCards(cardsJson.cards);
}, []);
return (
<div>
{
cards &&
cards.map((card, index) => (
<div key={card.name} className="cardHero">
<div className="front">{card.name}</div>
<div
className="back"
></div>
</div>
))
}
</div>
);
}
Note I put the cards.json in the same folder as the Cards component, I'm not outputting the image and I updated the dependency array.
If you only want to display the cards there is no reason for them to be inside a useEffect. I recommend you to create a constant and initialize it with cardsJson.cards, like:
const cards = cardsJson.cards;
Or if you want to play with states, just initialize your state with cardsJson.cards, like:
const [cards, setCards] = useState(cardsJson.cards);

Resources