卡组件不会重新渲染
Card Component wont re-render
出于某种原因,当我调用 API 时,我的卡片不会重新呈现。
当信息在后台更新时,它不会在前台显示,除非我刷新应用程序。
我正在传递信息作为道具并获取公司名称、地址和 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>
);
};
每当父组件更新属性 info
时,CpoCard
将 re-render。您可以通过在组件中包含 console.log('rerendered)
来简单地对其进行测试。
根据您在问题中的措辞,问题似乎出在 re-render 但更可能是您的 CpoCard
组件结构。
在 React 中,每当组件首次加载时,它都会将其状态创建为您在 useState
中设置的任何初始值。稍后,除非调用 setter 函数,否则状态不会发生变化或充电。这会将组件触发到 re-render。否则您不能设置状态值。
在您的例子中,在 CpoCard
组件中,道具 info
仅用于通过 useState(info.companies[0].companyName)
设置初始状态值。因此,该值是在组件的第一次加载时设置的。但后来,无论 info
属性如何变化 - 无论组件 re-renders.
多少次,状态都不会改变
简单例子:
在 CpoCard
加载 <CpoCard info={'initial value'} />
-> 组件 CpoCard
通过 useState
创建状态并将其值存储为传递 const [info, setinfo] = useState(props.info)
-> 组件渲染。
稍后在线 info
属性更改 <CpoCard info={'second value'} />
-> 组件 CpoCard
re-renders info
从 const [info, setinfo] = useState(props.info)
保持初始值'initial value'
因为你不能像这样改变状态值。初始值会一直保持,不管有多少re-renders,除非调用settersetInfo
并改变
所以在你的情况下你的结构是问题所在。
我不确定为什么你甚至将每个单独的道具存储到它自己的状态中——这似乎是一个结构本身的缺陷。如果您获得传递值 - 使用它们。如果出于某种原因您实际上需要为每个值使用一个状态,那么还有一个解决方法 - useEffect
useEffect
hook 允许你监听变化并据此做出反应。
所以你应该在一个正在监听你的 info
道具变化的 useEffect
中调用每个 setter:
useEffect(() => {
setCompanyName(info.companies[0].companyName)
setAddress(info.companies[0].city)
setPhoneNumber(info.companies[0].phoneNumber)
setEmployeeID(info.userId.employeeId)
}, [info])
有了这个 useEffect
发生的事情是组件加载初始值,将其存储在状态中并呈现。每当 prop.info
更改组件 re-renders 时,useEffect
依赖项数组(最后的 []
)检查 prop.info
是否更改,因此它执行函数( useEffect
钩子中的代码)根据新的 info
属性设置状态,并导致组件 re-render 再次显示新数据。
出于某种原因,当我调用 API 时,我的卡片不会重新呈现。 当信息在后台更新时,它不会在前台显示,除非我刷新应用程序。
我正在传递信息作为道具并获取公司名称、地址和 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>
);
};
每当父组件更新属性 info
时,CpoCard
将 re-render。您可以通过在组件中包含 console.log('rerendered)
来简单地对其进行测试。
根据您在问题中的措辞,问题似乎出在 re-render 但更可能是您的 CpoCard
组件结构。
在 React 中,每当组件首次加载时,它都会将其状态创建为您在 useState
中设置的任何初始值。稍后,除非调用 setter 函数,否则状态不会发生变化或充电。这会将组件触发到 re-render。否则您不能设置状态值。
在您的例子中,在 CpoCard
组件中,道具 info
仅用于通过 useState(info.companies[0].companyName)
设置初始状态值。因此,该值是在组件的第一次加载时设置的。但后来,无论 info
属性如何变化 - 无论组件 re-renders.
简单例子:
在 CpoCard
加载 <CpoCard info={'initial value'} />
-> 组件 CpoCard
通过 useState
创建状态并将其值存储为传递 const [info, setinfo] = useState(props.info)
-> 组件渲染。
稍后在线 info
属性更改 <CpoCard info={'second value'} />
-> 组件 CpoCard
re-renders info
从 const [info, setinfo] = useState(props.info)
保持初始值'initial value'
因为你不能像这样改变状态值。初始值会一直保持,不管有多少re-renders,除非调用settersetInfo
并改变
所以在你的情况下你的结构是问题所在。
我不确定为什么你甚至将每个单独的道具存储到它自己的状态中——这似乎是一个结构本身的缺陷。如果您获得传递值 - 使用它们。如果出于某种原因您实际上需要为每个值使用一个状态,那么还有一个解决方法 - useEffect
useEffect
hook 允许你监听变化并据此做出反应。
所以你应该在一个正在监听你的 info
道具变化的 useEffect
中调用每个 setter:
useEffect(() => {
setCompanyName(info.companies[0].companyName)
setAddress(info.companies[0].city)
setPhoneNumber(info.companies[0].phoneNumber)
setEmployeeID(info.userId.employeeId)
}, [info])
有了这个 useEffect
发生的事情是组件加载初始值,将其存储在状态中并呈现。每当 prop.info
更改组件 re-renders 时,useEffect
依赖项数组(最后的 []
)检查 prop.info
是否更改,因此它执行函数( useEffect
钩子中的代码)根据新的 info
属性设置状态,并导致组件 re-render 再次显示新数据。