The code below was designed to update a voting system. It works fine by displaying the results as the page loads.
Here is my problem: I need to update each user's vote any time the Get Vote Count button is clicked.
In the backend, I have php code which returns the array data as per below.
Can someone help me with displaying the array values and updating eg (vote to 11) depending on how the user voted?
<?php
// Update user response on a post
$return_arr[]= array("vote"=>"11");
echo json_encode($return_arr);
exit;
?>
Here is the array return by axios API Call
[{"vote":"11"}]
Here is the code
import React, { Component, Fragment } from "react";
import { render } from "react-dom";
import axios from 'axios';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
loading: false
};
}
componentDidMount() {
this.setState({
data: [
{ id: "1", name: "Tony", vote: "3" },
{ id: "2", name: "Mark", vote: "6" },
{ id: "3", name: "Joy", vote: "2" }
]
});
}
handleVote(person_id, person_vote) {
const data_vote = {
person_id: person_id,
person_vote: person_vote
};
axios
.get("http://localhost/vote.php", { data_vote })
.then(response => {
this.setState({ result_vote: response.data });
console.log(this.state.result_vote);
})
.catch(error => {
console.log(error);
});
}
render() {
return (
<span>
<label>
<ul>
{this.state.data.map((person, i) => (
<li key={i}>
{person.name} --(vote count: {person.vote})
<br />
<input
type="button"
value="Get Vote Counts"
onClick={() => this.handleVote(person.id, person.vote)}
/>
</li>
))}
</ul>
</label>
</span>
);
}
}
You should set your data state after getting the vote data from the fetch response. You have person_id in your handler and getting an array including vote value. So, map through your data state find the relevant person and update its vote value.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
loading: false
};
}
componentDidMount() {
this.setState({
data: [
{ id: "1", name: "Tony", vote: "3" },
{ id: "2", name: "Mark", vote: "6" },
{ id: "3", name: "Joy", vote: "2" }
]
});
}
handleVote(person_id, person_vote) {
const data_vote = {
person_id: person_id,
person_vote: person_vote
};
axios
.get("http://localhost/vote.php", { data_vote })
.then(response => {
const newData = this.state.data.map(person => {
if (person.id !== person_id) return person;
return { ...person, vote: response.data[0].vote };
});
this.setState(state => ({
data: newData
}));
})
.catch(error => {
console.log(error);
});
}
render() {
return (
<span>
<label>
<ul>
{this.state.data.map(person => (
<li key={person.id}>
{person.name} --(vote count: {person.vote})
<br />
<input
type="button"
value="Get Vote Counts"
onClick={() => this.handleVote(person.id, person.vote)}
/>
</li>
))}
</ul>
</label>
</span>
);
}
}
Try to avoid using an index as a key. You have a person.id so use it in your map method. Also, as an enhancement, you can refactor your code and create a Person component. You can pass the related data and vote handler then setup the update logic there.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
loading: false,
};
}
componentDidMount() {
this.setState({
data: [
{ id: "1", name: "Tony", vote: "3" },
{ id: "2", name: "Mark", vote: "6" },
{ id: "3", name: "Joy", vote: "2" },
],
});
}
handleVote = (person) => {
const data_vote = {
person_id: person.id,
person_vote: person.vote,
};
axios
.get("http://localhost/vote.php", { data_vote })
.then((response) => {
const newData = this.state.data.map((el) => {
if (el.id !== person.id) return el;
return { ...el, vote: response.data[0].vote };
});
this.setState({ data: newData });
})
.catch((error) => {
console.log(error);
});
};
render() {
return (
<span>
<label>
<ul>
{this.state.data.map(person => (
<Person
key={person.id}
person={person}
handleVote={this.handleVote}
/>
))}
</ul>
</label>
</span>
);
}
}
const Person = (props) => {
const { person, handleVote } = props;
const onVote = () => handleVote(person);
return (
<li>
{person.name} --(vote count: {person.vote})
<br />
<input type="button" value="Get Vote Counts" onClick={onVote} />
</li>
);
};
So, since your handler function is getting the person_id and your call is returning the new vote count, you should update the current person object in your data table in state.
Here is an example:
Updating the vote count for the current user
Related
there are similiar questions in stackoverflow but I I did not find what I was looking for.
I have a donorDonationForm which is a class componenet that connected to the redux state. The porpuse of that componenet is to collect inormation about a person that want to donate electronics items. At this point, I want to save those items in an array (maybe with an object in the future).
my redux state save the donor info and the reducer looks like this:
import {CHANGE_INPUT_FIELD} from '../utils/constants';
const initialStateInputs = {
// update the state
donorFields: {
name: '',
phone: '',
area: '',
yeshuv: '',
address: ''
// dateOfOffer: ''
},
donationFields: {
// donorID: '',
// vulonteerID: '',
type: [],
quantity: 1,
status: 'NOT_HANDLED',
comments: ''
// lastDateHandled: ''
}
// }, items: [ //need to add quantity
// {id: 1, name: "LAPTOP", isChecked: false, label: 'מחשב'},
// {id: 2, name: "HEADPHONES", isChecked: false, label: 'אוזניות'},
// {id: 3, name: "OTHER", isChecked: false, label: 'אחר'},
// ]
}
export const donorDonationInputsReducer = ( state = initialStateInputs, action={} ) => {
switch(action.type) {
case CHANGE_INPUT_FIELD:
return Object.assign( {}, state,
{
donorFields : {...state.donorFields,...action.payload},
donationFields: {...state.donationFields,...action.payload},
// items : {...state.items,...action.payload},
// isChecked: action.payload
})
default:
return state;
}
}
As you can see the items is commented by now, and I am managing the state of the item in a local state, and that how the comp looks like:
import React, {Component} from 'react';
import { connect } from 'react-redux';
import { setInputField } from '../actions/formAction';
import CheckBox from '../components/CheckBox/CheckBox';
import FormInput from '../components/FormInput/FormInput';
import {selectAreasOptions_2} from '../utils/constants';
import "./form.css";
const mapStateToProps = (state) => {
return {
donorFields: state.donorDonationInputsReducer.donorFields,
donationFields: state.donorDonationInputsReducer.donationFields
}
}
const mapDispatchToProps = dispatch => {
return {
onInputChange: event => {
const {name, value} = event.target;
dispatch(setInputField( { [name]:value} ) )
}
}
}
class donorDonationForm extends Component {
constructor() {
super();
this.state = {
items: [
{id: 1, name: "LAPTOP", isChecked: false, label: 'מחשב'},
{id: 2, name: "HEADPHONES", isChecked: false, label: 'אוזניות'},
{id: 3, name: "OTHER", isChecked: false, label: 'אחר'},
]
,
type: []
}
}
handleCheckChieldElement = (event) => {
let {items, type} = this.state;
let arr = [];
items.forEach(item => {
if (item.name === event.target.value) {
item.isChecked = event.target.checked;
// console.log(`item.name :${item.name }`);
// console.log(`event.target.value :${event.target.value}`);
// console.log(`event.target.checked :${event.target.checked}`);
}
})
items.map(item => item.isChecked ? arr.push(item.name) : null)
this.setState({items: [...items], type: [...arr]});
}
onButtonSubmit = (event) => {
console.log(this.props.donorFields);
event.preventDefault();
fetch('http://localhost:8000/api/donor', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
...this.props.donorFields
})
})
.then(response => response.json())
.then(resp => console.log(resp))
.catch( err => console.log(err) )
}
// componentDidUpdate(prevProps, prevState) {
// const {items, type} = this.state;
// // const type = [];
// if (prevState.items !== items) {
// console.log('items state has changed');
// items.map (item => item.isChecked ?
// this.setState({type: [...type,item.name]}) : null)
// // if (item.isChecked) { type.push(item.name) } ;
// console.log(type);
// }
// }
render() {
console.log(this.state.items);
console.log(this.state.type);
const { onInputChange } = this.props;
return (
<div>
<h1 className="pt4"> פרטי תורם</h1>
<form className=" black-80 pt2" >
<section className=" grid-container">
<FormInput
id="name"
name="name"
type="text"
onInputChange={onInputChange}
label="שם "
required
/>
<FormInput
id="phone"
name="phone"
type="tel"
onInputChange={onInputChange}
label="מספר טלפון "
required
/>
<FormInput
id="address"
name="address"
type="text"
onInputChange={onInputChange}
label="כתובת "
required
/>
<FormInput
id="yeshuv"
name="yeshuv"
type="text"
onInputChange={onInputChange}
label="עיר "
required
/>
<FormInput
id="comments"
name="comments"
onInputChange={onInputChange}
label="הערות "
required
/>
<FormInput
id="area"
name="area"
onInputChange={onInputChange}
label="איזור "
select={selectAreasOptions_2}
/>
{/* type */}
<div className="measure-narrow">
<label htmlFor="type" className="f5 b db mb2">מעוניין לתרום
<span className="normal black-60"> *</span>
</label>
{
this.state.items.map( (item, i) => {
return (
<CheckBox
key={i}
onChange={this.handleCheckChieldElement}
checked={ item.isChecked }
value= {item.name}
label = {item.label}
/>
);
})
}
</div>
</section>
<input type="submit" value="שלח"
className="b bg-light-blue pa2 hover pointer"
onClick={this.onButtonSubmit}
/>
</form>
</div>
);
}
}
export default connect(mapStateToProps, mapDispatchToProps)(donorDonationForm);
My main goal is that the type array - the final donation, will update the redux state before submitting this form. I tried with componentDidUpdate but didn't make it. What is the best way for tracking the checked items, updating the array and then update the type array which is the final donation in the redux state? should I do that in the onButtonSubmit method - before sending the data to the server (and thats way saving the looping over the items array for searching the checked elements) ?
Better approach would be do inside onButtonSubmit
Let me briefly explain the tasks:
inputChangeHandler to update this.state.items
Go with the final this.state.items value Array of items inside onButtonSubmit
After getting API response update the application level Redux state with Array of items.
Note: Dispatch the action. Reducer will update the Redux state. Following code will do this:
// Action
export const setItems = (data) => (dispatch) => {
dispatch({type: 'SET_ITEMS', payload: data})
}
// mapDispatchToProps
const mapDispatchToProps = (dispatch) =>
bindActionCreators(
{
setItems,
...others
},
dispatch
)
// onSubmitButton
onButtonSubmit = (event) => {
console.log(this.props.donorFields);
event.preventDefault();
fetch('http://localhost:8000/api/donor', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
...this.props.donorFields
})
})
.then(response => this.props.setItems(response.json())) // will update the state.
.then(resp => console.log(resp))
.catch( err => console.log(err) )
}
// Reducer
export const donorDonationInputsReducer = ( state = initialStateInputs, action={} ) => {
switch(action.type) {
case CHANGE_INPUT_FIELD:
return Object.assign( {}, state,
{
donorFields : {...state.donorFields,...action.payload},
donationFields: {...state.donationFields,...action.payload},
// items : {...state.items,...action.payload},
// isChecked: action.payload
})
case SET_ITEMS:
return {
...state,
items: action.payload
}
default:
return state;
}
}
That's it.
Happy Coding :)
I cannot implement delete button.
I have api endpoint 'DELETE /.../{id}'.
Have ApiService.js:
deleteById(id) {
return axios.delete(`${ACCOUNT_API_BASE_URL}/${id}`)
}
and here is my class:
class Account extends Component {
constructor(props) {
super(props);
this.state = {
item: {
id: props.match.params.id,
name: '',
email: '',
password: '',
link: ''
}
};
this.deleteById = this.deleteById.bind(this);
}
componentDidMount() {
// eslint-disable-next-line
if (this.state.item.id === -1) {
return -1
}
ApiService.fetchAccountById(this.state.item.id)
.then(response => this.setState({
item: {
name: response.data.name,
email: response.data.email,
password: response.data.password,
link: response.data.link
}
}))
}
deleteById(id) {
ApiService.deleteById(id)
.then(res => console.log(res.data))
}
render() {
return (
<div>
<h3>{this.state.item.name}</h3>
<ul>
{this.state.item.id}
<li className={c.itemEmail}>Email: {this.state.item.email}</li>
<li>Password: {this.state.item.password}</li>
<li>Link: {this.state.item.link}</li>
</ul>
<button onClick={this.deleteById(this.state.item.id)}>Delete</button>
</div>
)
}
}
It deletes data after requesting page(get method), but not by clicking delete button.
If I set this.deleteById to <button onClick= to , I receive:
'DELETE http://localhost:8080/api/.../undefined 400'
First, you are removing the id property from you item in componentDidMount:
ApiService.fetchAccountById(this.state.item.id)
.then(response => this.setState({
item: { // now item doesn't have id anymore
name: response.data.name,
email: response.data.email,
password: response.data.password,
link: response.data.link
}
}))
So keep your id like this:
ApiService.fetchAccountById(this.state.item.id)
.then(response => this.setState({
item: {
id: this.state.item.id,
name: response.data.name,
email: response.data.email,
password: response.data.password,
link: response.data.link
}
}))
Second, you are executing the function instead of passing the function to onClick, change your onClick value to:
onClick={() => {this.deleteById(this.state.item.id)}}
<button onClick={() => this.deleteById(this.state.item.id)}>Delete</button>
I am making API calls and rendering different components within an object. One of those is illustrated below:
class Bases extends Component {
constructor() {
super();
this.state = {
'basesObject': {}
}
}
componentDidMount() {
this.getBases();
}
getBases() {
fetch('http://localhost:4000/cupcakes/bases')
.then(results => results.json())
.then(results => this.setState({'basesObject': results}))
}
render() {
let {basesObject} = this.state;
let {bases} = basesObject;
console.log(bases);
//FALSY values: undefined, null, NaN, 0, false, ""
return (
<div>
{bases && bases.map(item =>
<button key={item.key} className="boxes">
{/* <p>{item.key}</p> */}
<p>{item.name}</p>
<p>${item.price}.00</p>
{/* <p>{item.ingredients}</p> */}
</button>
)}
</div>
)
}
}
The above renders a set of buttons. All my components look basically the same.
I render my components here:
class App extends Component {
state = {
ordersArray: []
}
render() {
return (
<div>
<h1>Bases</h1>
<Bases />
<h1>Frostings</h1>
<Frostings />
<h1>Toppings</h1>
<Toppings />
</div>
);
}
}
I need to figure out the simplest way to, when a button is clicked by the user, add the key of each clicked element to a new array and I am not sure where to start. The user must select one of each, but is allowed to select as many toppings as they want.
Try this
We can use the same component for all categories. All the data is handled by the parent (stateless component).
function Buttons({ list, handleClick }) {
return (
<div>
{list.map(({ key, name, price, isSelected }) => (
<button
className={isSelected ? "active" : ""}
key={key}
onClick={() => handleClick(key)}
>
<span>{name}</span>
<span>${price}</span>
</button>
))}
</div>
);
}
Fetch data in App component, pass the data and handleClick method into Buttons.
class App extends Component {
state = {
basesArray: [],
toppingsArray: []
};
componentDidMount() {
// Get bases and toppings list, and add isSelected attribute with default value false
this.setState({
basesArray: [
{ key: "bases1", name: "bases1", price: 1, isSelected: false },
{ key: "bases2", name: "bases2", price: 2, isSelected: false },
{ key: "bases3", name: "bases3", price: 3, isSelected: false }
],
toppingsArray: [
{ key: "topping1", name: "topping1", price: 1, isSelected: false },
{ key: "topping2", name: "topping2", price: 2, isSelected: false },
{ key: "topping3", name: "topping3", price: 3, isSelected: false }
]
});
}
// for single selected category
handleSingleSelected = type => key => {
this.setState(state => ({
[type]: state[type].map(item => ({
...item,
isSelected: item.key === key
}))
}));
};
// for multiple selected category
handleMultiSelected = type => key => {
this.setState(state => ({
[type]: state[type].map(item => {
if (item.key === key) {
return {
...item,
isSelected: !item.isSelected
};
}
return item;
})
}));
};
// get final selected item
handleSubmit = () => {
const { basesArray, toppingsArray } = this.state;
const selectedBases = basesArray.filter(({ isSelected }) => isSelected);
const selectedToppings = toppingsArray.filter(({ isSelected }) => isSelected);
// submit the result here
}
render() {
const { basesArray, toppingsArray } = this.state;
return (
<div>
<h1>Bases</h1>
<Buttons
list={basesArray}
handleClick={this.handleSingleSelected("basesArray")}
/>
<h1>Toppings</h1>
<Buttons
list={toppingsArray}
handleClick={this.handleMultiSelected("toppingsArray")}
/>
</div>
);
}
}
export default App;
CSS
button {
margin: 5px;
}
button.active {
background: lightblue;
}
I think the following example would be a good start for your case.
Define a handleClick function where you can set state with setState as the following:
handleClick(item) {
this.setState(prevState => {
return {
...prevState,
clickedItems: [...prevState.clickedItems, item.key]
};
});
}
Create an array called clickedItems in constructor for state and bind handleClick:
constructor() {
super();
this.state = {
basesObject: {},
clickedItems: [],
}
this.handleClick = this.handleClick.bind(this);
}
You need to add a onClick={() => handleClick(item)} handler for onClick:
<button key={item.key} className="boxes" onClick={() => handleClick(item)}>
{/* <p>{item.key}</p> */}
<p>{item.name}</p>
<p>${item.price}.00</p>
{/* <p>{item.ingredients}</p> */}
</button>
I hope that helps!
I developed a list which get the data of my product, I try that with the fetch and I get the data on the console but It not rendering on the list.
My code is :
constructor(props) {
super(props);
this.state = {
products :[],
id:props.match.params.id
}
}
componentWillReceiveProps(nextProps) {
console.log("nextProps", nextProps);
}
componentDidMount() {
fetch('http://172.16.234.24:8000/api/productDetail/'+this.props.match.params.id)
.then(Response => Response.json())
.then(data =>
{console.log(data.productDetails)
this.setState({ products: data.productDetails})})
}
render() {
let {products} = this.state;
console.log(products)
return (
<div><Well><strong>The details of your product: </strong>
<ul>
<li><strong>Product name :</strong></li><br/>
<li><strong>Categorie name :</strong></li><br/>
<li><strong>TaxRate :</strong></li><br/>
<li><strong>Description :</strong></li><br/>
</ul>
<ul>{products && products.length && products.map(product => (
<li key={product.id}>
{console.log(product.id)}
<li>{product.name}</li><br/>
<li>{product.categorie_id}</li><br/>
<li>{product.taxRate}</li><br/>
<li>{product.description}</li><br/>
</li>))}
</ul>
</Well></div>
)
}
}
when I run it, I get the data on the console :
but my list is empty like that :
How can I fix that ?
From what I understood, this is the result you are looking for :
const data = [
{
id: 8,
name: "AAAA",
categorie_id: 45,
taxRate: 78,
description: "Wow, so cool"
},
{
id: 15,
name: "BBBB",
categorie_id: 8,
taxRate: 5,
description: "damn"
},
{
id: 86,
name: "BBBBBBBFFFF",
categorie_id: 876,
taxRate: 0,
description: "hey, you !"
}
]
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
products: [],
//id: props.match.params.id
}
}
componentDidMount() {
this.setState({ products: data })
}
render() {
const { products } = this.state;
return (
<div>
{products && products.length && products.map(({id, name, categorie_id, taxRate, description}) =>
<div key={id}>
<strong>The details of your product: </strong>
<ul>
<li><strong>Product name : </strong>{name}</li><br />
<li><strong>Categorie name : </strong>{categorie_id}</li><br />
<li><strong>TaxRate : </strong>{taxRate}</li><br />
<li><strong>Description : </strong>{description}</li><br />
</ul>
</div>
)}
</div>
)
}
}
ReactDOM.render(<App/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root'>
You should include the product field name into the map function.
EDIT
From your console output I think you likely forgot to take the right value in your data :
fetch('http://172.16.234.24:8000/api/productDetail/'+this.props.match.params.id)
.then(Response => Response.json())
.then(data =>
{console.log(data)
this.setState({ products: data.['product details'] })})
Just add .['product details']to take the details from your data.
EDIT 2
If your data is not an array, the following code should be enough :
const data = {
id: 8,
name: "AAAA",
categorie_id: 45,
taxRate: 78,
description: "Wow, so cool"
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
products: [],
//id: props.match.params.id
}
}
componentDidMount() {
this.setState({ products: data })
}
render() {
const { products: { name, categorie_id, taxRate, description } } = this.state;
return (
<div>
<strong>The details of your product: </strong>
<ul>
<li><strong>Product name : </strong>{name}</li><br />
<li><strong>Categorie name : </strong>{categorie_id}</li><br />
<li><strong>TaxRate : </strong>{taxRate}</li><br />
<li><strong>Description : </strong>{description}</li><br />
</ul>
</div>
)
}
}
ReactDOM.render(<App/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root'>
Hope your data looks like below:
this.state = {
product_details: {
Categorie: {},
categorie_id: 4,
name: "Testview",
id: 33,
description: "yes it works",
rate: 0,
vat: {},
vat_id: 2
}
};
to render this in list :
import React, { Component } from 'react';
import { render } from 'react-dom';
class App extends Component {
constructor() {
super();
this.state = {
product_details: {
Categorie: {},
categorie_id: 4,
name: "Testview",
id: 33,
description: "yes it works",
rate: 0,
vat: {},
vat_id: 2
}
};
}
render() {
const {name, categorie_id, id, description} = this.state.product_details;
return (
<>
<strong>The details of your product: </strong>
<ul>
<li><strong>Product name : </strong><span>{name}</span></li><br/>
<li><strong>Categorie name :</strong><span>{categorie_id}</span></li><br/>
<li><strong>TaxRate :</strong><span>{id}</span></li><br/>
<li><strong>Description :</strong><span>{description}</span></li>
</ul>
</>
);
}
}
render(<App />, document.getElementById('root'));
Demo link on this available here
Edit :
As you need to render object on the list item, that will be available here
Based on this previous questions I made (Show fetch results in render return() in React.js), from which I received json results, I now need to count the number of sofas that each brand has. For example, Brand X has 2 occurences and Brand Y has 3043.
I get the brand from one sofa by calling myUrlApi + /couch-model on fetch and the json is something like what you can see in the picture below.
Has you can see each sofa has associated to itself a brand. What I want to count is how many sofa each brand has.
I'll put my current code here:
export class Main extends React.Component {
constructor(props) {
super(props);
this.state = {
token: {},
isLoaded: false,
models: []
};
}
componentDidMount() {
/*code to generate token, not needed for the purpose of the question*/
fetch(url + "/couch-model/?limit=9", {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: "JWT " + JSON.parse(localStorage.getItem("token")).token
}
})
.then(res => {
if (res.ok) {
return res.json();
} else {
throw Error(res.statusText);
}
})
.then(json => {
this.setState(
{
models: json.results
},
() => {}
);
});
}
render() {
const { isLoaded, models } = this.state;
if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div>
{models.map(model => (
<a href="/sofa" key={model.id}>
<div className="Parcelas">
<img src={img_src} className="ParcImage" alt="sofa" />
<h1>Sofá {model.name}</h1>
<h2>
1,200<span>€</span>
</h2>
<p
className="Features"
dangerouslySetInnerHTML={{ __html: model.description }}
/>
<button className="Botao">
<p className="MostraDepois">Ver Detalhes</p>
<span>+</span>
</button>
<img
src="../../img/points.svg"
className="Decoration"
alt="points"
/>
</div>
</a>
))}
</div>
);
}
}
}
Hope I was clear, ask if you have any doubt.
if your results look like this as you said in your post :
{
results: [
{
brand: { name: "Brand-A", image: "", etc: "..." },
category: "A",
code: "AAA",
name: "SofaA",
price: 1200
},
{
brand: { name: "Brand-A", image: "", etc: "..." },
category: "A",
code: "AAA",
name: "SofaB",
price: 1200
},
{
brand: { name: "Brand-B", image: "", etc: "..." },
category: "A",
code: "AAA",
name: "SofaC",
price: 1200
}
]
}
You can add a state property like sofasPerBrand initialized to {}
constructor(props) {
super(props);
this.state = {
token: {},
isLoaded: true,
models: [],
sofasPerBrand: {}
};
}
And add in the setState function in componentDidMount the RIYAJ KHAN reduce function like this :
this.setState(
{
models: json.results,
sofasPerBrand: json.results.reduce((coundData, sofa, index) => {
if (!!coundData[sofa.brand.name]) {
coundData[sofa.brand.name] += 1;
} else {
coundData[sofa.brand.name] = 1;
}
return coundData;
}, {})
},
() => { }
);
then you can declare it in your render function :
const { isLoaded, models, sofasPerBrand } = this.state;
and use it like that any where :
<ul>
{Object.keys(sofasPerBrand).map(brand=>(
<li>{brand} : {sofasPerBrand[brand]}</li>
))}
</ul>
One can use javascript#reducers for it.
models.reduce((coundData,sofa,index)=>{
if(!!coundData[sofa.brand.name]){
coundData[sofa.brand.name] +=1;
}else{
coundData[sofa.brand.name]=1;
}
return coundData;
}, {})