Reputation: 134
So what I want is to have a list of TouchableOpacities which represent the days of the following week. The idea is, when I press any given day, its style changes between "selected" and "unselected"
Card with desired buttons for days
My understanding is that (and I'm kind of a newbie), to force the component to re-render when I want the style to change, I must change the state. And this state should be in the parent component, whose code is the following:
import React, { useState, useEffect } from "react";
import DaySelector from "./DaySelector";
const WeekList = () => {
const [activeDays, setActiveDays] = useState([]);
function onClick(index) {
let days = [...activeDays];
let day = days[index];
days[index].active = !day.active;
setActiveDays(days);
}
useEffect(() => {
let date = new Date();
let tempArr = [];
for (let i = 0; i < 7; i++) {
let temp = new Date();
temp.setDate(date.getDate() + i);
tempArr.push({
key: temp.getDay(),
day: temp,
active: true,
onPress: () => onClick(i),
});
}
setActiveDays(tempArr);
}, []);
return (
<>
{activeDays.map((day) => (
<DaySelector
key={day.key}
day={day.day}
active={day.active}
onClick={day.onPress}
/>
))}
</>
);
};
export default WeekList;
However, I keep getting the error in the title: "TypeError: undefined is not an object (evaluating 'day.active')", refering to line 10 of the 'onClick' (let day = days[index];) function, whose job is to toggle the "active" property the object, which should then propagate to the component, where a simple ternary operator uses it to choose the style to apply.
The thing is, I've console.logged the hell out of the program and it either works (but doesn't actually change the style of the DaySelector component) or it crashes, despite the logs saying "day" is indeed an object.
In short, I don't know what I'm doing wrong... and it seemed so simple at the beginning... Thanks in advance for any help!
Upvotes: 0
Views: 548
Reputation: 3649
Setting the onPress function on the object state seemed fishy to me. So I rewrote it without that and it works.
/**
* Define the behavior of the component here.
* Keep on data on the state.
*/
const onClick = (index: number) => {
// Update a field in an object in a list _without mutating_ the objects.
setActiveDays([
...activeDays.slice(0, index),
{ ...activeDays[index], active: !activeDays[index].active },
...activeDays.slice(index + 1),
]);
};
// Then
{activeDays.map((day: any, i: number) => (
<DaySelector
key={day.key}
day={day.day}
active={day.active}
onClick={() => onClick(i)}
/>
))}
Upvotes: 1