I am rendering a component for every item in a flatList. Each component has a label, and when the component is rendered, I have a useEffect that fetches the updated label name for that specific label.
For some reason, it seems to only be running for the last item in the flatList. The last item is the only item with the updated name, while all other still contain the outdated information.
Assuming there is an updated name for each label, why could my useEffect only be running on the last item?
function renderLabel({ label }) {
return <Label label={label} onPress={() => onPressLead(label)}/>;
}
<FlatList
data={labels}
keyExtractor={keyExtractor}
renderItem={renderItem}
/>
Label.js - I would think this would run for every label component rendered. Could there be a possible issue with what I have here? Or must it be somewhere else in my code?
let name = label.name;
useEffect(() => {
updateLabel()
name = label.name
}, [label]);
return (
<>
{name}
</>
)
CodePudding user response:
I see several possible issues. Some important code is missing, so I'll answer what I can.
- You're not using state to hold your label name in the Label component (
name = label.name
), so React will never know to re-render the component when it changes. It's rare to need to use alet
variable in React. To hold properties that the component needs to change, use the useState hook.
However, you shouldn't do that here, because of the next point.
- It looks like you are updating the label somewhere else, and also locally (
name = label.name
). Don't do this, it's too easy for the two to get out of sync and cause bugs. If the name is coming from somewhere else, show it and set it from props.
I'm not sure what updateLabel()
does or where it comes from (how does the function know what to update the label to?), but if you need it, it should come from props.
If
label.name
is a string, you can't render it in a fragment. You must render it in a Text component.<Text>{label.name}</Text>
The object that FlatList passes in to the renderItem callback does not have a property called
label
, you are looking foritem
- this is the object from thedata
prop.
function renderLabel({ item }) { // item, not label
return <Label label={item} onPress={() => onPressLead(item)}/>;
}
const Label = ({ label, updateLabel }) => {
// no local label variable
useEffect(() => {
updateLabel(); // what is this supposed to do?
}, []); // no dependencies, if you only want to update the label once on mount
return <Text>{label.name}</Text>; // if label.name is a string
};
// your FlatList is fine as written
CodePudding user response:
Your use effect probably needs the label as a dependency.
useEffect(() => {
updateLabelName()
}, [label]);