Skrivet av burton666:
Jag har stött på ytterligare ett problem. Någon som har något tips på hur jag löser "hasRating" som jag använder överallt lite smidigare?
import React, { useState } from 'react'
import ReactDOM from 'react-dom'
const Button = ({ onClick, text }) => {
return (
<>
<button onClick={onClick}>
{text}
</button>
</>
)
}
const Display = ({ text }) => {
return (
<h1>{text}</h1>
)
}
const History = ({ hasRating }) => {
if (!hasRating) {
return (
<>
<h1>statistics</h1>
<p>No feedback given</p>
</>
)
}
return (<h1>statistics</h1>)
}
const Statistics = ({ text, value, hasRating }) => {
if (hasRating) {
return (
<tr>
<td>{text}</td>
<td>{value}</td>
</tr>
)
}
return null
}
const average = (good, bad, total) => {
return ((good - bad) / total)
}
const positive = (good, total) => {
return ((good / total) * 100 + " %")
}
const App = () => {
// save clicks of each button to own state
const [good, setGood] = useState(0)
const [neutral, setNeutral] = useState(0)
const [bad, setBad] = useState(0)
const totalRatings = good + neutral + bad
const hasRatings = totalRatings > 0
return (
<div>
<Display text="give feedback" />
<Button onClick={() => setGood(good + 1)} text="good" />
<Button onClick={() => setNeutral(neutral + 1)} text="neutral" />
<Button onClick={() => setBad(bad + 1)} text="bad" />
<History hasRating={hasRatings} />
<table>
<tbody>
<Statistics text="good" value={good} hasRating={hasRatings} />
<Statistics text="neutral" value={neutral} hasRating={hasRatings} />
<Statistics text="bad" value={bad} hasRating={hasRatings} />
<Statistics text="all" value={totalRatings} hasRating={hasRatings} />
<Statistics text="average" value={average(good, bad, totalRatings)} hasRating={hasRatings} />
<Statistics text="positive" value={positive(good, totalRatings)} hasRating={hasRatings} />
</tbody>
</table>
</div>
)
}
ReactDOM.render(<App />, document.getElementById('root')
)
Nu har jag aldrig använt React hooks, så det var intressant att se hur man kan göra det utan class components. Dock känns det lite rörigare att förstå, men är säkert nice då man jobbat med det, globalt state likt Redux.
Var även ett tag sen jag satt med React, så ska se om jag kan lyckas hjälpa dig!
Som ovan nämner så behöver inte Statistics veta om ifall ett objekt har en rating, det ända den vill göra är att printa ut något till DOM, samma gäller History.
Så i din render skulle vi kunna göra exempelvis så här:
<h1>statistics</h1>
{ !hasRatings && <p>No feedback given</p> }
<table>
<tbody>
{
hasRatings &&
<Fragment>
<Statistics text="good" value={good} />
<Statistics text="neutral" value={neutral} />
<Statistics text="bad" value={bad} />
<Statistics text="all" value={totalRatings} />
<Statistics text="average" value={average(good, bad, totalRatings)} />
<Statistics text="positive" value={positive(good, totalRatings)} />
</Fragment>
}
</tbody>
</table>
Jag har valt att ta bort History då jag tycker den funktionen inte har något riktigt syfte. Du kan lika gärna sätta en <h1> i din render här. Sen med en check på hasRatings om den är false så kan du visa No feedback given.
Sedan kan du med hjälp av React.Fragmemt gruppera flera nodes.
Här säger vi att OM hasRatings är true OCH skriv ut detta (vilket alltid är true).
Plockar bort hasRatings från Statistics
const Statistics = ({ text, value }) => {
return (
<tr>
<td>{text}</td>
<td>{value}</td>
</tr>
)
}
TIPS:
Du kan se över om du kan hålla dina värden i en array, så att du kan få ut alla dina värden via en .map(). På så vis slipper du skriva flera olika <Statistics>, då functionen ändå är dynamisk och kan hantera alla värden du skickar in.
Sparar tangenttryck för trötta fingrar och gör koden lite kortare och lättare att jobba med om man skulle vilja utöka.
Exempel
state = {
ratings: [
good = {
text: "textvalue",
value: 1
},
bad = {
text: "textvalue",
value: 2
},
...etc
]
}
this.state.ratings.map((rating, i) => {
return (<Statistics text={rating.text} value={rating.value} key={i} />)
});