0

I'm trying to change a value from a select menu. My code is working, but I think this would go better if I used useReducer.Am I correct? I tried to change it, but I just can't seem to make it work... At the documentation it says that:

"useReducer is usually preferable to useState when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one."

I think I should be using it right?

 const [diametro, setDiametro] = useState(0);
 const [total, setTotal] = useState("0");
 useEffect(
     () => setTotal(() => ((preco / 100) * diametro).toFixed(2).replace(".", ",")), [diametro]
      );
rafaelpadu
  • 1,134
  • 2
  • 6
  • 20
  • I think even `useEffect` could be overkill already. Why not call `setTotal` directly wherever you are currently updating `diametro` and `preco`? Keep in mind that code should be easy to read and maintain and the incurred asynchronicity of `useEffect` might already be confusing – let alone `useReducer`! – digitalbreed Aug 24 '21 at 21:59

1 Answers1

0

I think useMemo is the correct hook to use in your case. Basically, you are 'deriving' the value of total from the current value of diametro. This means that the value of total only changes if the value of diametro changes.

The code would then look something like this:

const [diametro, setDiametro] = useState(0);
const total = useMemo(() =>
  ((preco / 100) * diametro).toFixed(2).replace(".", ","),
  [diametro]
);

In general, a guiding principle is to keep the actual state to the bare minimum, and then use hooks like useMemo to derive the other properties you need. Remember that is is also okay to return multiple properties as an object from useMemo, so you can derive multiple values with only one useMemo call.

vitoke
  • 660
  • 4
  • 11
  • Thanks man. Worked it just great! Just to clarify one think, the application is changing correctly but I placed a console.log at the useMemo function and this console is one state behind, why is that? – rafaelpadu Aug 26 '21 at 00:16
  • Good to hear! The console.log problem can depend on where and how you log the values. The `setDiametro` function does not immediately change the value of `diametro`. This is an important reason to have correct dependency arrays as last parameter to hooks. – vitoke Aug 26 '21 at 05:25
  • So, to make sure you are logging the latest value of `total`, you need to use useEffect: `useEffect(() => console.log({ total }), [total])` In this way React will make sure to call console.log at the right point in time when `diametro` and `total` are in sync. If you don't use `useEffect`, or supply a different dependency array, unexpected things may happen. This is inherent to the way hooks work in React I'm afraid. – vitoke Aug 26 '21 at 05:32