React Apex Chart Data, Image and API - arrays

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

Related

Not able to fetch data from API using React Router

I am trying to make a demo project using a free API available in web. I am trying to fetch using js fetch method and I am using the latest react-router-dom package
App.js is setting up the route with appropriate loaders
App.js
import "./App.css";
import Root from "./layouts/Root";
import { RouterProvider, createBrowserRouter } from "react-router-dom";
import Posts from "./pages/Posts";
import { loader as allPostsLoader } from "./pages/Posts";
const router = createBrowserRouter([
{
path: "/",
element: <Root />,
Children: [{ index: true, element: <Posts />, loader: allPostsLoader }],
},
]);
function App() {
return (
<>
<RouterProvider router={router} />
</>
);
}
export default App;
Posts.js
import { json } from "react-router-dom";
import { useLoaderData } from "react-router-dom";
import PostsList from "../components/PostsList";
const Posts = () => {
const data = useLoaderData();
console.log(data);
return (
<PostsList posts={data} />
);
};
export default Posts;
export const loader = async () => {
const response = await fetch("https://dummyapi.io/data/v1/post", {
method: "GET",
headers: new Headers({
"app-id": "63e0971cd1c871fb16613cc4",
}),
body:undefined
});
if (!response.ok) {
throw json({ message: "Count not fetch data!!" }, { status: 500 });
}
return response;
};
PostsList.js
const PostsList = ({ posts }) => {
return (
<div className="all-post">
<h1>All Posts</h1>
<div className="posts-wrapper">
{posts.map((post) => {
<div key={post.id} className="post">
<div className="image">
<img src={post.image} alt="" />
</div>
<h2>{post.text}</h2>
<p>Publish Date: {post.publishDate}</p>
</div>
})}
;
</div>
</div>
);
};
export default PostsList;
Response from API
{
"data": [
{
"id": "60d21b4667d0d8992e610c85",
"image": "https://img.dummyapi.io/photo-1564694202779-bc908c327862.jpg",
"likes": 43,
"tags": [
"animal",
"dog",
"golden retriever"
],
"text": "adult Labrador retriever",
"publishDate": "2020-05-24T14:53:17.598Z",
"owner": {
"id": "60d0fe4f5311236168a109ca",
"title": "ms",
"firstName": "Sara",
"lastName": "Andersen",
"picture": "https://randomuser.me/api/portraits/women/58.jpg"
}
},
{
"id": "60d21b4967d0d8992e610c90",
"image": "https://img.dummyapi.io/photo-1510414696678-2415ad8474aa.jpg",
"likes": 31,
"tags": [
"snow",
"ice",
"mountain"
],
"text": "ice caves in the wild landscape photo of ice near ...",
"publishDate": "2020-05-24T07:44:17.738Z",
"owner": {
"id": "60d0fe4f5311236168a10a0b",
"title": "miss",
"firstName": "Margarita",
"lastName": "Vicente",
"picture": "https://randomuser.me/api/portraits/med/women/5.jpg"
}
}
],
"total": 873,
"page": 0,
"limit": 20
}
I am not able to see the app call in the Network section and now errors are shown as well.

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 use json data for react-select?

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 (....);
}

concat two json objects from different api by id in axios get and store

I have a question about how to add the second nested api query in axios. The second api query to get the json object based on the id from the first api array json. And then concat to global array in function Retrieve()?
first api url:
'/api/sets'
second api children:
'/api/sets/' + todo.id + '/tasks'
responce global json from first api url:
[
{
"id": 121,
"name": "list1",
"description": "description1"
},
{
"id": 9,
"name": "list2",
"description": "description2"
}
]
responce second json children from api by id first api:
[
{
"id": 1,
"name": "task1",
"description": "description task1"
},
{
"id": 2,
"name": "task2",
"description": "description task2"
}
]
and finally expected combined stored array json
[
{
"id": 121,
"name": "list1",
"description": "description1",
"task": [{
"id": 1,
"name": "task1",
"description": "description task1"
},
{
"id": 2,
"name": "task2",
"description": "description task2"
}
]
},
{
"id": 9,
"name": "list2",
"description": "description2",
"task": [{
"id": 10,
"name": "task1",
"description": "description task1"
},
{
"id": 11,
"name": "task2",
"description": "description task2"
}
]
}
]
code js:
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { Provider } from 'mobx-react';
import TodoStore from './store';
const Root = (
<Provider TodoStore={TodoStore}>
<App />
</Provider>
);
ReactDOM.render(Root, document.getElementById('root'));
store.js
import React from 'react';
import { observable, action, configure, runInAction } from 'mobx';
import axios from 'axios';
configure({ enforceActions: 'observed' });
class TodoStore {
#observable todos = [];
#action Retrieve = () => {
axios
.get('/api/sets')
.then(response => {
let tempTodos = response.data;
runInAction(() => {
this.todos = tempTodos;
});
})
.catch(error => {
console.log(error);
});
};
}
const store = new TodoStore();
export default store;
If you API does not support GraphQL endpoint, then you should have to expand your Retrive() action and do extra XHR request for sets id to combine results from API endpoint 1 and 2.
#action Retrieve = () => {
axios
.get('/api/sets')
.then(response => {
let tempTodos = response.data;
let todosWithTasks = tempTodos.map(todo => {
let tasks = null;
axios.get('/api/sets/' + todo.id + '/tasks')
.then(response2 => {
tasks = response2.data;
}).catch(error => {
console.log(error);
});
todo.task = tasks;
return todo;
});
// `todosWithTasks` is joined API1 and API2
})
.catch(error => {
console.log(error);
});
};
Thanks it works, all api is joined, now I have another little problem. If set #observable.ref todos = []; or #observable.shallow todos = []; in console log key task exitst with array of objects, but when I set #observable todos = []; key task no exist.
console.log
(2) [{…}, {…}]
0:
description: "false"
id: 121
name: "list1"
task: Array(2)
0: {id: 10, name: "task1", description: "description task1", state: false, position: 1}
1: {id: 11, name: "task2", description: "description task2", state: true position: 2}
length: 2
__proto__: Array(0)
__proto__: Object
1:
description: "false"
id: 9
name: "list2"
task: Array(2)
0: {id: 3, name: "task1", description: "description task1", state: false, position: 3}
1: {id: 7, name: "task2", description: "description task2", state: false, position: 5}
length: 2
__proto__: Array(0)
__proto__: Object
length: 2
__proto__: Array(0)
and if try map key task
index.module.js:206 Uncaught TypeError: Cannot read property 'map' of undefined
at eval (TodoItem.jsx:17)
at eval (index.module.js:220)
at eval (index.module.js:198)
at trackDerivedFunction (mobx.module.js:1212)
at Reaction.track (mobx.module.js:1752)
at useObserver (index.module.js:196)
at wrappedComponent (index.module.js:220)
at renderWithHooks (react-dom.development.js:12938)
at updateFunctionComponent (react-dom.development.js:14627)
at updateSimpleMemoComponent (react-dom.development.js:14573)
react-dom.development.js:17117 The above error occurred in the <wrappedComponent> component:
in wrappedComponent (created by n)
in n (created by inject-with-TodoStore(Object))
in inject-with-TodoStore(Object) (created by App)
in div (created by App)
in App (created by n)
in n (created by inject-with-TodoStore(App))
in inject-with-TodoStore(App)
in e
code index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
import { Provider } from 'mobx-react';
import TodoStore from './TodoStore';
import registerServiceWorker from './registerServiceWorker';
const Root = (
<Provider TodoStore={TodoStore}>
<App />
</Provider>
);
ReactDOM.render(Root, document.getElementById('root'));
registerServiceWorker();
TodoStore.js
import React from 'react';
import {observable, action, computed, configure, runInAction} from 'mobx';
import axios from 'axios';
axios.defaults.baseURL = 'api';
configure({ enforceActions: 'observed' });
class TodoStore {
#observable.shallow todos = [];
#action Retrieve = () => {
axios
.get('/sets')
.then(response => {
let tempTodos = response.data;
let todosWithTasks = tempTodos.map(todo => {
let tasks = null;
axios
.get('/sets/' + todo.id + '/tasks')
.then(response2 => {
todo.task = response2.data;
})
.catch(error => {
console.log(error);
});
return todo;
});
runInAction(() => {
this.todos = todosWithTasks;
});
})
.catch(error => {
console.log(error);
});
};
}
const store = new TodoStore();
export default store;
app.js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import TodoItem from './TodoItem';
import { toJS } from 'mobx';
import { inject, observer } from 'mobx-react';
#inject('TodoStore')
#observer
class App extends Component {
render() {
const TodoStore = this.props.TodoStore;
console.log(toJS(TodoStore.todos));
return (
<div className="App">
{TodoStore.todos.map(todo => (
<TodoItem key={todo.id} todo={todo} />
))}
</div>
);
}
async componentDidMount() {
this.props.TodoStore.Retrieve();
}
}
TodoItem.wrappedComponent.propTypes = {
todo: PropTypes.object.isRequired,
TodoStore: PropTypes.object.isRequired
};
export default App;
todoitem
import React from 'react';
import PropTypes from 'prop-types';
import { inject, observer } from 'mobx-react';
import TodoItemTask from './TodoItemtask';
const TodoItem = inject('TodoStore')(
observer(props => {
const TodoStore = props.TodoStore;
return (
<>
<div key={props.todo.id} className="todo-item">
<span>{props.todo.id}</span>
<h5>{props.todo.name}</h5>
<p>{props.todo.description}</p>
{props.todo.task.map((item, index) => (
<TodoItemTask key={index + item.id} item={item} />
))}
</div>
</>
);
})
);
TodoItem.wrappedComponent.propTypes = {
todo: PropTypes.object.isRequired,
TodoStore: PropTypes.object.isRequired
};
export default TodoItem;
TodoItemTask.js
import React from 'react';
import PropTypes from 'prop-types';
import { inject, observer } from 'mobx-react';
const TodoItemTask = inject('TodoStore')(
observer(props => {
const TodoStore = props.TodoStore;
return (
<>
<div key={props.item.id} className="todo-item">
<span>{props.index}</span>
<p>{props.item.name}</p>
<p>{props.item.description}</p>
</div>
</>
);
})
);
TodoItemTask.wrappedComponent.propTypes = {
item: PropTypes.object.isRequired,
TodoStore: PropTypes.object.isRequired
};
export default TodoItemTask;
no errors and render all data if set static data
#observable todos = [
{
"id": 121,
"name": "list1",
"description": "description1",
"task": [{
"id": 1,
"name": "task1",
"description": "description task1"
},
{
"id": 2,
"name": "task2",
"description": "description task2"
}
]
},
{
"id": 9,
"name": "list2",
"description": "description2",
"task": [{
"id": 10,
"name": "task1",
"description": "description task1"
},
{
"id": 11,
"name": "task2",
"description": "description task2"
}
]
}
];
Actually, this is not a problem with mobx, I found that two api url json are incorrectly connected in this function.
In console.log(todosWithTasks) it looks right, but this console.log (JSON.stringify(todosWithTasks)) not.
this is actual code
import React from 'react';
import {observable, action, computed, configure, runInAction} from 'mobx';
import axios from 'axios';
axios.defaults.baseURL = 'api';
configure({ enforceActions: 'observed' });
class TodoStore {
#observable todos = [];
#action async Retrieve = () => {
this.isLoading = true;
await axios
.get('/sets')
.then(async response => {
let tempTodos = response.data;
tempTodos.forEach(todo => (todo.task = []));
let todosWithTasks = tempTodos.map(todo => {
axios
.get('/sets/' + todo.id + '/tasks')
.then(response2 => {
todo.task = response2.data;
return todo;
})
.catch(error => {
console.log(error);
});
return todo;
});
runInAction(() => {
console.log(todosWithTasks);
console.log(JSON.stringify(todosWithTasks));
this.todos = todosWithTasks;
});
})
.catch(error => {
console.log(error);
});
};
}
const store = new TodoStore();
export default store;
output from console.log(JSON.stringify(todosWithTasks))
[{"id":1,"name":"list1","description":"description1","task":[]}]
output from console.log(todosWithTasks) looks fine
(1) [{…}]
0:
description: "description1"
id: 1
name: "list1"
task: Array(1)
0: {id: 1, name: "task1", description: "description task1"}
length: 1
__proto__: Array(0)
__proto__: Object
length: 1
__proto__: Array(0)
therefore, it does not render in the map function, because the key task is empty.
If the modified merged json file localy, in axios it's everything ok. In console.log (JSON.stringify (todosWithTasks)) everything fine.
#action Retrieve() {
axios
.get('localhost:3000/src/data.json')
.then(response => {
let tempTodos = response.data;
tempTodos.forEach(todo => (todo.editing = false));
runInAction(() => {
this.todos = tempTodos;
console.log(JSON.stringify(tempTodos));
});
})
.catch(error => {
console.log(error);
});
}

Rendering a nested object state

This problem is giving me a huge headache so any help is welcome :)
In this component, I'm making 2 axios calls to different APIs: one for freegeoip and one for openweathermap. I'm storing the data in the currentCity state, which is an object with 2 keys, location and weather. The idea is that the app detects your current location (using freegeoip) and renders location name and weather data (using openweathermap).
I'm positive it's storing the state properly as console logs have confirmed. I can render the location data for currentCity state, but can't seem to render the weather data for currentCity state.
renderCurrentCity(city) {
console.log('state3:', this.state.currentCity);
console.log([city.weather.main]);
return(
<div>
<li>{city.location.city}, {city.location.country_name}</li> // Working
<li>{city.weather.main.temp}</li> // Not working
</div>
)
}
The console error I get:
Uncaught (in promise) TypeError: Cannot read property '_currentElement' of null
currentCity.location JSON:
{
"ip": // hidden,
"country_code": "FR",
"country_name": "France",
"region_code": "GES",
"region_name": "Grand-Est",
"city": "Reims",
"zip_code": "",
"time_zone": "Europe/Paris",
"latitude": 49.25,
"longitude": 4.0333,
"metro_code": 0
}
currentCity.weather JSON:
{
"coord": {
"lon": 4.03,
"lat": 49.25
},
"weather": [
{
"id": 800,
"main": "Clear",
"description": "clear sky",
"icon": "01d"
}
],
"base": "stations",
"main": {
"temp": 283.15,
"pressure": 1011,
"humidity": 43,
"temp_min": 283.15,
"temp_max": 283.15
},
"visibility": 10000,
"wind": {
"speed": 3.1,
"deg": 350
},
"clouds": {
"all": 0
},
"dt": 1493127000,
"sys": {
"type": 1,
"id": 5604,
"message": 0.1534,
"country": "FR",
"sunrise": 1493094714,
"sunset": 1493146351
},
"id": 2984114,
"name": "Reims",
"cod": 200
}
Rest of code:
import React, { Component } from 'react';
import axios from 'axios';
import WeatherList from './weatherlist';
import SearchBar from './searchbar';
const API_KEY = '95108d63b7f0cf597d80c6d17c8010e0';
const ROOT_URL = 'http://api.openweathermap.org/data/2.5/weather?'
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
cities: [],
errors: '',
currentCity: {
location: {},
weather: {}
}
};
this.currentCity();
this.renderCurrentCity = this.renderCurrentCity.bind(this);
}
citySearch(city) {
const url = `${ROOT_URL}&appid=${API_KEY}&q=${city}`;
axios.get(url)
.then(response => {
const citiesArr = this.state.cities.slice();
this.setState({
cities: [response.data, ...citiesArr],
errors: null
});
})
.catch(error => {
this.setState({
errors: 'City not found'
})
})
}
currentCity() {
var city;
var country;
axios.get('http://freegeoip.net/json/')
.then(response => {
const lat = response.data.latitude;
const lon = response.data.longitude;
city = response.data.city;
country = response.data.country_name;
const url = `${ROOT_URL}&appid=${API_KEY}&lat=${lat}&lon=${lon}`;
const state = this.state.currentCity;
console.log('state1:',state);
this.setState({
currentCity: { ...state, location: response.data }
});
console.log(url);
axios.get(url)
.then(city => {
const state = this.state.currentCity;
console.log('state2:', state);
this.setState({
currentCity: { ...state, weather: city.data }
});
})
})
}
renderCurrentCity(city) {
console.log('state3:', this.state.currentCity);
console.log([city.weather.main]);
return(
<div>
<li>{city.location.city}, {city.location.country_name}</li>
<li>{city.weather.main.temp}</li>
</div>
)
}
render() {
return (
<div className={this.state.cities == false ? 'search': 'search-up'}>
<h1>What's the weather today?</h1>
<ul className='list-unstyled text-center'>
{this.renderCurrentCity(this.state.currentCity)}
</ul>
<SearchBar
onSearchSubmit={this.citySearch.bind(this)}
errors={this.state.errors} />
{this.state.cities == false ? null : <WeatherList cities={this.state.cities} />}
</div>
)
}
}
You are spreading your whole state when your receive the weather data:
this.setState({
currentCity: { ...state, weather: city.data }
});
it should be:
this.setState({
currentCity: { ...state.currentCity, weather: city.data }
});

Resources