I'm pretty new to react, and I'm working on a component where I'm calculating the percentages of values in below useState, so for instance:
const [data, setData] = useState({ five: 5, four: 4, three: 3, two: 2, one: 1 });
const [percentage, setPercentage] = useState(0);
const fields = [
{ name: "five", value: data.five },
{ name: "four", value: data.four },
{ name: "three", value: data.three },
{ name: "two", value: data.two },
{ name: "one", value: data.one }
];
useEffect(() => {
const per1 = ((data.one) / (data.five data.four data.three data.two data.one)) * 100;
setPercentage(per1);
}, [data]);
I have constants that I created to calculated the amount of ratings for each type of rating for instance: the number of five star, four star, etc. :
const numRating5 = product.reviews.filter((x) => x.rating === 5);
const numRating4 = product.reviews.filter((x) => x.rating === 4);
const numRating3 = product.reviews.filter((x) => x.rating === 3);
const numRating2 = product.reviews.filter((x) => x.rating === 2);
const numRating1 = product.reviews.filter((x) => x.rating === 1);
Is there a way for me to put the numRating5, numRating4,.... in their respective positions (five:5, four:4,...) in the useState. I would really appreciate any help or guidance on this. Thank you!
CodePudding user response:
You can try something like this:
const product = {
reviews: [
{rating: 1},
{rating: 2},
{rating: 3},
{rating: 4},
{rating: 5},
]
};
const getNumRating = (num) => product.reviews.filter((x) => x.rating === num).length;
const numRating5 = getNumRating(5);
const numRating4 = getNumRating(4);
const numRating3 = getNumRating(3);
const numRating2 = getNumRating(2);
const numRating1 = getNumRating(1);
const useState = React.useState;
const useEffect = React.useEffect;
function App() {
const [data, setData] = useState({
five: numRating5,
four: numRating4,
three: numRating3,
two: numRating2,
one: numRating1
});
const [percentage, setPercentage] = useState(0);
useEffect(() => {
const per1 = (
data.one / (data.five data.four data.three data.two data.one)
) * 100;
setPercentage(per1);
}, [data]);
return (
<div>
Hello! Percentage = {percentage}
</div>
);
}
ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
CodePudding user response:
you can update the data using setData and pass the object
setData ({
five : numRating5,
four : numRating4,
three : numRating3,
two : numRating2,
one : numRating1,
});
please check: https://reactjs.org/docs/hooks-state.html for further information
CodePudding user response:
You can pass any data to useState
but the shape of it should generally match what you intend to use in the state variable you declare with it. The state variable should represent a useful way to work with your data.
Since we generally use state to keep track of changing data in our apps, below is just an another example that may help to think about this as well as some useful patterns for updating state along with getting your percentage and using it on render. You're working with a list of reviews for each star rating level as I see it. This example can apply to bigger lists or lists of entirely different objects too.
The idea is each object consistently describes the features or information you need about each thing (in your case a list of reviews) allowing for methods of working with the data that avoid the need for individually calculating values (avoiding the repetition of something like per1
or numRatingX
as the size or shape of your data changes).
https://codesandbox.io/s/tender-brattain-gu3d7f?file=/src/App.js:0-1064
Click the button to reset the review data with random values and see percentages update.
import { useState } from "react";
const App = () => {
const seedRatings = [
{ stars: "5", reviews: 134 },
{ stars: "4", reviews: 177 },
{ stars: "3", reviews: 67 },
{ stars: "2", reviews: 55 },
{ stars: "1", reviews: 21 }
];
const [ratings, setRatings] = useState(seedRatings);
const total = ratings.reduce((total, rating) => total rating.reviews, 0);
// some thing that changes your data
const handleChangeReviews = () => {
// say we get some new ratings
const newRatings = ratings.map((rating) => {
return { ...rating, reviews: Math.floor(Math.random() * 100) };
});
setRatings(newRatings);
};
return (
<div>
{ratings &&
ratings.map(({ stars, reviews }) => (
<div key={stars}>
<span>{stars} star reviews: </span>
<span>{reviews} </span>
<span>Percent of total: {(reviews / total) * 100}%</span>
</div>
))}
<button onClick={handleChangeReviews}>Change reviews</button>
</div>
);
};
export default App;