For some reason, my card won't re-render when I make a call to the API. when the information updates in the backend it doesn't display in the front unless I refresh the app.
I'm passing down info as a prop and grabbing the company name, address, and phone.
const CpoCard = ({ info, navigation }) => {
const [companyName, setCompanyName] = useState(info.companies[0].companyName);
const [address, setAddress] = useState(info.companies[0].city);
const [phoneNumber, setPhoneNumber] = useState(info.companies[0].phoneNumber);
const [employeeID, setEmployeeID] = useState(info.userId.employeeId);
const { setSelectedEmployee } = useCompany();
const handleEditPress = () => {
setSelectedEmployee(info);
navigation.navigate('DeleteEmployee');
//deleteEmployee
};
const handlePress = () => {
console.log(info);
navigation.navigate('CpoInfo', { info: info });
};
return (
<View style={styles.outerContainer}>
{
<View style={styles.innerContainer}>
<View style={styles.mainContent}>
<Image
style={styles.employeeImg}
source={require('~assets/pngs/avatar.png')}
/>
<View style={styles.companyInfoContainer}>
<TouchableOpacity onPress={handlePress}>
<Text style={{ fontSize: 18, fontWeight: 'bold' }}>
{companyName !== null ? `${companyName} ` : 'info'}
</Text>
<Text>{`Phone Number: ${phoneNumber}`}</Text>
<Text>{`address: ${address}`}</Text>
</TouchableOpacity>
</View>
</View>
</View>
}
</View>
);
};
CodePudding user response:
Whenever the prop info
is being updated by the parent component, the CpoCard
will re-render. You could simply test it by including console.log('rerendered)
in the component.
Based on your wording in your question it seems the issue isint the re-render but more likely your structure of a CpoCard
component.
In React, whenever the component first loads, it creates its states to whatever initial value you set in useState
. Later down the line the state will not mutate nor charge unless the setter function is called. That triggers the component to re-render. You can NOT set the state value otherwise.
In your case, in the CpoCard
component, the prop info
is ONLY used to set the initial state value via useState(info.companies[0].companyName)
. So the value is being set on the first load of a component. But later on, regardless how info
prop changes - the state will NOT change regardless of how many times the component re-renders.
Simple example:
At CpoCard
load <CpoCard info={'initial value'} />
-> component CpoCard
creates a state via useState
and stores its value as passed const [info, setinfo] = useState(props.info)
-> component renders.
Later down the line info
prop changes <CpoCard info={'second value'} />
-> component CpoCard
re-renders info
from const [info, setinfo] = useState(props.info)
remains the initial value 'initial value'
since you can not change the state value like so. The initial value will remain for the entire time, regardless of how many re-renders, unless called the setter setInfo
and changes.
So in your case your structure is the issue.
I am unsure why you even store each individual prop into its own state - it seems like a flaw in a structure by itself. If you are getting passed values - use those. If for some reason you actually require to use a state for each value then there is also a work around - useEffect
useEffect
hook allows you to listen to changes and react based on that.
So you should call each setter in a useEffect
that is listening to your info
prop change:
useEffect(() => {
setCompanyName(info.companies[0].companyName)
setAddress(info.companies[0].city)
setPhoneNumber(info.companies[0].phoneNumber)
setEmployeeID(info.userId.employeeId)
}, [info])
With this useEffect
what happens is the component loads the initial value, stores it in state and renders. Whenever the prop.info
changes the component re-renders, the useEffect
dependency array (the []
in the end) checks that prop.info
changes hence it executes the function (the code inside the useEffect
hook) that sets the states based on new info
prop and that causes a component to re-render once again displaying the new data.