BS100
BS100

Reputation: 873

Why do I not need to set useState when a value is from props?

I'm rendering a list which is updated according to a filter update as below.

const Expenses = (props) => {
  const [filteredYear, setFilteredYear] = useState('2020');

  const defaultExpenseData = props.items.filter(
    (b) => b.date.getFullYear() === 2020
  );

  const [filteredExpenseData, setFilteredExpensesData] =
    useState(defaultExpenseData);

  const filterChangeHandler = (selectedYear) => {
    setFilteredYear(selectedYear);
    const filteredExpense = props.items.filter(
      (b) => b.date.getFullYear() == selectedYear
    );
    setFilteredExpensesData(filteredExpense);
    console.log(filteredExpense);
  };

  return (
    <div>
      <Card className="expenses">
        <ExpensesFilter
          selected={filteredYear}
          onChangeFilter={filterChangeHandler}
        />
        {filteredExpenseData.length == 0 && <p>No data</p>}
        {filteredExpenseData.length > 0 &&
          filteredExpenseData.map((expense) => (
            <ExpenseItem
              key={expense.id}
              title={expense.title}
              amount={expense.amount}
              date={expense.date}
            />
          ))}
      </Card>
    </div>
  );
};

As far as I understood, react renders according to some value changes when the value is managed by useState.

However, above still works especially when I don't set a useState for filteredExpensesData as below.

const Expenses = (props) => {
  const [filteredYear, setFilteredYear] = useState('2020');

  // const defaultExpenseData = props.items.filter(
  //   (b) => b.date.getFullYear() === 2020
  // );

  // const [filteredExpenseData, setFilteredExpensesData] =
  //   useState(defaultExpenseData);

  const filteredExpense = props.items.filter(
    (b) => b.date.getFullYear().toString() === filteredYear
  );

  const filterChangeHandler = (selectedYear) => {
    setFilteredYear(selectedYear);
    // const filteredExpense = props.items.filter(
    //   (b) => b.date.getFullYear() == selectedYear
    // );
    // setFilteredExpensesData(filteredExpense);
    // console.log(filteredExpense);
  };

  return (
    <div>
      <Card className="expenses">
        <ExpensesFilter
          selected={filteredYear}
          onChangeFilter={filterChangeHandler}
        />
        {filteredExpense.length == 0 && <p>No data</p>}
        {filteredExpense.length > 0 &&
          filteredExpense.map((expense) => (
            <ExpenseItem
              key={expense.id}
              title={expense.title}
              amount={expense.amount}
              date={expense.date}
            />
          ))}
      </Card>
    </div>
  );
};

In the latter code, I commented out all the lines which is related to state management of the filtered data.

Why is it? only reason I could think of is "maybe some data derived from props, wouldn't require useState"

Can anyone help me to understand on this behavior?

Upvotes: 0

Views: 96

Answers (1)

cesarvargas
cesarvargas

Reputation: 182

items is a state.

Somewhere along your app, the items state is passed to props. Whenever items mutates, everywhere in your app where the items state is used, react will re-render if the values have changed.

You do not need to re-create a state that mirrors items.

Upvotes: 1

Related Questions