• Empleos
  • Sobre nosotros
  • profesionales
    • Inicio
    • Empleos
    • Cursos y retos
  • empresas
    • Inicio
    • Publicar vacante
    • Nuestro proceso
    • Precios
    • Evaluaciones
    • Nómina
    • Blog
    • Comercial
    • Calculadora de salario

0

163
Vistas
array of objects as props won't give me the proper values

I want to make a progress bar and I have two components. this is my chart component:

import Bar from "./Bar";

const INIT_MONTH_EXPENSES = [
  { label: "Jan", value: 0 },
  { label: "Feb", value: 0 },
  { label: "Mar", value: 0 },
  { label: "Apr", value: 0 },
  { label: "May", value: 0 },
  { label: "Jun", value: 0 },
  { label: "Jul", value: 0 },
  { label: "Aug", value: 0 },
  { label: "Sep", value: 0 },
  { label: "Oct", value: 0 },
  { label: "Nov", value: 0 },
  { label: "Dec", value: 0 },
];

const Chart = (props) => {
  const totalExpenseAmountOfYear = props.items.reduce((total, item) => {
    total = +total + +item.amount;
    return total;
  }, 0);

  for (const expense of props.items) {
    const expenseMonth = expense.date.getMonth();
    INIT_MONTH_EXPENSES[expenseMonth].value += expense.amount;
  }
  //INIT_MONTH_EXPENSES[2].value give me the expected value but props.expenses[2].value in the Bar component give me a wrong value(actually doubled value) 
  return (
    <div className="bg-pink-200 w-full h-[150px] p-4 mb-8 flex">
      <Bar
        expenses={INIT_MONTH_EXPENSES}
        totalAmount={totalExpenseAmountOfYear}
      />
    </div>
  );
};

export default Chart;

the problem is that when i log passed props "expenses" in the other component it give me wrong values . any help will be appreciated.

almost 3 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

When you pass an object declared in the parent component to the child component, in order for react to render the components again for the updated state you will have to use useState or useReducer hooks to notify the react engine that something has changed and I need you to re render the components again.

In the example you are just mutating the existing object and when you do that react has no idea that something has changed, so it ends up not rendering the child component with the updated data.

import Bar from "./Bar";
import { useState, useEffect } from 'react';

const INIT_MONTH_EXPENSES = [{
    label: "Jan",
    value: 0
  },
  {
    label: "Feb",
    value: 0
  },
  {
    label: "Mar",
    value: 0
  },
  {
    label: "Apr",
    value: 0
  },
  {
    label: "May",
    value: 0
  },
  {
    label: "Jun",
    value: 0
  },
  {
    label: "Jul",
    value: 0
  },
  {
    label: "Aug",
    value: 0
  },
  {
    label: "Sep",
    value: 0
  },
  {
    label: "Oct",
    value: 0
  },
  {
    label: "Nov",
    value: 0
  },
  {
    label: "Dec",
    value: 0
  },
];

const Chart = (props) => {
  // store the expenses in state so that it can be passed along.
  // only run the initializer when the component is mounted
  const [expenses, setExpenses] = useState(() => {
       return [...INIT_MONTH_EXPENSES];
  });
  const [totalExpenses, setTotalExpenses] = useState(0);
  
  const {
     items
  } = props;
  
  useEffect(() => {
     const updatedExpenses = items.reduce((memo, item) => {
        const expenseMonth = item.date.getMonth();
        
        if(memo[expenseMonth]) {
           memo[expenseMonth].value += expense.amount;
        }
        
        return memo;
     }, [...expenses]);
     
     // this will notify react that state changed and will re render the component
     setExpenses(updatedExpenses);
  }, [items]);
  
  // use effect to cal total expenses
  useEffect(() => {
     const totalExpenseAmountOfYear = items.reduce((total, item) => {
          total = +total + (+item.amount);
         
          return total;
     }, 0);
     
     setTotalExpenses(totalExpenseAmountOfYear);
  }, [items]);

  return ( <
    div className = "bg-pink-200 w-full h-[150px] p-4 mb-8 flex" >
    <
    Bar expenses = {
      expenses
    }
    totalAmount = {
      totalExpenses
    }
    /> <
    /div>
  );
};

export default Chart;
<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>

Also need to make sure that setState is not called directly in the render. It should typically be called in useEffect, so you will have to figure out when the expenses need to be updated.

almost 3 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Nuestro proceso Comercial
Legal
Términos y condiciones Política de privacidad
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recomiéndame algunas ofertas
Necesito ayuda