How to simplify rendering mathmatics in React

Viewed 31

I have this exercise, where I have to do math calculations all the time with PROPS, which results in extremely long code. Do you know how to simplify this ?

import React, { useState } from 'react'
const Button = (props) => (
  <button onClick={props.handleClick}>
    {props.text}
  </button>
)
const Statistics = (props) => {
  if (props.allClicks.length === 0) {
    return (
      <div>
        <h2>No feedback given</h2>
      </div>
    )
  }
  return (
    <div>
      <p>good {props.allClicks.filter(x => x === "G").length}</p>
      <p>neutral {props.allClicks.filter(x => x === "N").length}</p>
      <p>bad {props.allClicks.filter(x => x === "B").length}</p>
      <p>all {props.allClicks.length}</p>
      <p>average {(props.allClicks.length)/3}</p>
      <p>positive {100*(props.allClicks.length - props.allClicks.filter(x => x === "B").length)/(props.allClicks.length)} %</p>
    </div>
  )
}

This part is crazy long

 <p>good {props.allClicks.filter(x => x === "G").length}</p>
      <p>neutral {props.allClicks.filter(x => x === "N").length}</p>
      <p>bad {props.allClicks.filter(x => x === "B").length}</p>
      <p>all {props.allClicks.length}</p>
      <p>average {(props.allClicks.length)/3}</p>
      <p>positive {100*(props.allClicks.length - props.allClicks.filter(x => x === "B").length)/(props.allClicks.length)} %</p>
1 Answers

You can create a hook that counts the different types of clicks using Array.reduce(), and produces an object of counts which you can use in the component:

const { useMemo } = React

const useCountClicks = allClicks =>
  useMemo(() => allClicks.reduce((acc, x) => ({
    ...acc,
    [x]: (acc[x] || 0) + 1
  }), { all: allClicks.length }), [allClicks])

const Statistics = ({ allClicks }) => {
  const { all, G, N, B } = useCountClicks(allClicks)
  if (all === 0) {
    return (
      <div>
        <h2>No feedback given</h2>
      </div>
    )
  }
  return (
    <div>
      <p>good {G}</p>
      <p>neutral {N}</p>
      <p>bad {B}</p>
      <p>all {all}</p>
      <p>average {all/3}</p>
      <p>positive {100*(all - B)/(all)} %</p>
    </div>
  )
}

const allClicks = ['G', 'G', 'B', 'B', 'G', 'N']

ReactDOM.render(
  <Statistics allClicks={allClicks} />,
  root
)
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div>

Related