英文:
How to change display from another function in react native
问题
我有一个在React Native中的类似这样的东西:
function HomeScreen({navigation}) {
function startGenerate(exercises) {
console.log(exercises);
return (
<View style={global.container}>
<Button
title="Generate recommended exercises"
onPress={() => navigation.navigate('List', {exercises: exercises})}
/>
</View>
)
}
var exercises = [];
if (severityValue >= 7) {
return (
<View style={global.container}>
<Text>Test</Text>
</View>
)
} else if (severityValue != null) {
writePainProfile(areaValue, typeValue, severityValue);
onValue(ref(db, 'count'), (snapshot) => {
const count = snapshot.val();
exercises = filter(count);
return (startGenerate(exercises));
})
// 在这里调用exercises会返回一个空数组
}
// ...为简洁起见,这里省略了其他代码
}
export default HomeScreen
通过onValue
,我正在读取Firebase实时数据库,然后调用filter函数,该函数返回符合指定条件的数据列表。然后,我想通过startGenerate
函数创建一个显示筛选数据的页面,但似乎没有任何内容渲染出来。所以,有没有更好的方法来实现这个?
我还注意到,在onValue
之外尝试使用exercises
会返回一个空数组,可能是由于onValue
的工作方式,这显著复杂化了事情。
编辑:
这是exercises数组的格式,作为对象数组:
这是我尝试渲染exercises数组元素的方式:
return (
<View style={global.container}>
{exercises.map(exercise => {
return <Text>----</Text>;
})}
</View>
);
英文:
I have something in react native like this:
function HomeScreen({navigation}) {
function startGenerate(exercises) {
console.log(exercises);
return (
<View style = {global.container}>
<Button
title = "Generate recommended exercises"
onPress={() => navigation.navigate('List', {exercises: exercises})}
/>
</View>
)
}
var exercises = [];
if (severityValue >= 7) {
return (
<View style = {global.container}>
<Text>Test</Text>
</View>
)
} else if (severityValue!=null) {
writePainProfile(areaValue, typeValue, severityValue);
onValue(ref(db, 'count'), (snapshot) => {
const count = snapshot.val();
exercises = filter(count);
return (startGenerate(exercises));
})
//Calling exercises here returns an empty array
}
//...other code omitted here for brevity
}
export default HomeScreen
With the onValue
, I'm reading a firebase realtime database, and then calling the filter function, which returns a list of filtered data that fit the specified criteria. I then want to create a page that displays the filtered data and I've attempted to do this through the startGenerate
function, however nothing appears to be rendering. So, is there any better way to do this?
I've also noticed that attempting to use exercises
outside the onValue
returns an empty array, likely due to the way the onValue
works, which significantly complicates things.
Edit:
Here's how the exercises array is formatted, as an Array of objects
And here's how I am attempting to render elements of the exercises array:
return (
<View style={global.container}>
{exercises.map(exercise => {
return <Text>----</Text>
})};
</View>
);
答案1
得分: 1
无法看到代码,但我理解您的问题是关于React中状态更新的问题。在React中,直接更新本地变量不会触发重新渲染,因为React不会自动侦测这种变化。您需要使用useState
和useEffect
来管理状态,以便在数据发生更改时触发重新渲染。以下是您提供的示例的中文翻译:
import React from 'react';
import { View, Text, Button } from 'react-native';
function HomeScreen({ navigation }) {
const [exercises, setExercises] = React.useState([]);
React.useEffect(() => {
// 这是在组件挂载时调用的
writePainProfile(areaValue, typeValue, severityValue);
onValue(ref(db, 'count'), (snapshot) => {
const count = snapshot.val();
// 更新状态
setExercises(filter(count));
});
}, []);
if (severityValue >= 7) {
return (
<View style={global.container}>
<Text>测试</Text>
</View>
);
}
// 如果没有练习,显示占位符
if (!(exercises?.length > 0)) {
return (
<View style={global.container}>
<Text>加载中...</Text>
</View>
);
}
return (
<View style={global.container}>
<Button
title="生成推荐的练习"
onPress={() => navigation.navigate('List', { exercises: exercises })}
/>
{exercises.map((exercise) => {
return <Text>{exercise.name}</Text>;
})}
</View>
);
}
export default HomeScreen;
如果您有关于React或代码的更多问题,请随时提出。
英文:
The reason why nothing is rendering is that updating a local variable var exercises = [];
will not trigger a re-render in React. As onValue
takes in a callback so it is async. We must update the state once the callback fires to trigger the re-render. Also please keep in mind that local variables are not permanent between re renders and functions called in a components body will fire on every render so you could end calling onValue
more times than expected unless you use `useEffect. Instead, the way to achieve this would be to use React hooks to hold and set state. Please see example below:
import React from 'react';
import { View, Text, Button } from 'react-native';
function HomeScreen({ navigation }) {
const [exercises, setExercises] = React.useState([]);
// this is called on mount
React.useEffect(() => {
// running side effects
writePainProfile(areaValue, typeValue, severityValue);
onValue(ref(db, 'count'), (snapshot) => {
const count = snapshot.val();
// update state
setExercises(filter(count));
});
}, []);
if (severityValue >= 7) {
return (
<View style={global.container}>
<Text>Test</Text>
</View>
);
}
// if no exercises yet display a placeholder
if (!(exercises?.length > 0)) {
return (
<View style={global.container}>
<Text>Loading...</Text>
</View>
);
}
return (
<View style={global.container}>
<Button
title="Generate recommended exercises"
onPress={() => navigation.navigate('List', { exercises: exercises })}
/>
// this should work for the provided format
{exercises.map((exercise) => {
return <Text>{exercise.name}</Text>;
})}
</View>
);
}
export default HomeScreen;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论