I'm having a really weird problem with my React Native component. Component's state is correctly updated, but it is not reflected on what is rendered by the component.
Here is what my component looks like (I didn't include imports and other parts of the code that are irrelevant):
export default function MessageActionsModal({
message,
actions,
onClose
}) {
const [dimensions, setDimensions] = useState(null);
const [messageActions, setMessageActions] = useState([]);
useEffect(() => {
if (message !== null) {
setMessageActions(actions.map((a) => ({
...a,
onPress: () => {
a.onPress(message?.item);
onClose();
}
})))
} else {
setMessageActions([]);
}
}, [message, actions, onClose]);
if (message === null) {
return null;
}
return (
<Portal>
<TouchableOpacity
style={styles.messageActionsModal}
activeOpacity={0}
onPress={onClose}
>
<Portal style={styles.messageActionsModalInnerContainer}>
<MessageListItem
style={[
styles.message,
getMessagePositionAndDimensions(message)
]}
{...message.item}
/>
<View
style={[
styles.messageActionsMenu,
getMenuPosition(dimensions, message)
]}
{...dimensions === null && {
onLayout: ({ nativeEvent }) => setDimensions({
width: nativeEvent.layout.width,
height: nativeEvent.layout.height
})
}}
>
<Text>{'LEN'}{messageActions.length}</Text>
<Text>{'LOG'}{console.log(messageActions.length)}</Text>
{messageActions.map((a) => (
<Button
key={a.title}
style={styles.messageActionButton}
title={a.title}
variant="text"
startIcon={a.icon}
startIconProps={{
style: styles.messageActionButtonIconWrapper,
iconStyle: styles.messageActionButtonIcon,
fill: Colors.yellow
}}
onPress={a.onPress}
/>
))}
</View>
</Portal>
</TouchableOpacity>
</Portal>
);
}
So basically, after messageActions
are updated in the useEffect
, component renders incorrectly and neither message action is rendered (although one item should be rendered).
Another interesting thing is that the following code renders "LEN 0", but it logs "LOG 1" in the console.
<Text>{'LEN'}{messageActions.length}</Text>
<Text>{'LOG'}{console.log(messageActions.length)}</Text>
What am I doing wrong here?
You can try memoizing actions instead of using useEffect
. Here's an example:
const messageActions = useMemo(() => {
if (message === null) {
return [];
}
return actions.map((a) => ({
...a,
onPress: () => {
a.onPress(message?.item);
onClose();
}
}));
}, [message, actions, onClose]);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.