Home > Software engineering >  Card Component wont re-render
Card Component wont re-render

Time:05-01

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.

  • Related