英文:
Emptying the search screen after navigating away to a different screen
问题
这是您的搜索屏幕代码。如果您有其他问题或需要帮助,请随时提出。
import {
StyleSheet,
View,
ActivityIndicator,
FlatList,
Button,
} from 'react-native';
import React, { useState, useEffect } from 'react';
import AppTextInput from '../components/AppTextInput';
import Card from '../components/Card';
import colors from '../config/colors';
import axios from 'axios';
import { baseApiUrl, apikey } from '../api/config/apiLinks';
import AppPicker from '../components/AppPicker';
import AppText from '../components/AppText';
import { openBrowserAsync } from 'expo-web-browser';
const options = [
{ value: 'news', label: '新闻' },
{ value: 'videos', label: '视频' },
{ value: 'documentaries', label: '纪录片' },
{ value: 'channels', label: '频道' },
];
export default function SearchScreen({ navigation }) {
const [selected, setSelected] = useState(options[0]);
const [input, setInput] = useState();
const [resultRecords, setResultRecords] = useState([]);
const [totalPages, setTotalPages] = useState();
const [currentPage, setCurrentPage] = useState(1);
const [errorMessage, setErrorMessage] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [attachEnd, setAttachEnd] = useState(false);
const url =
baseApiUrl +
'/search/search-get.php?' +
apikey +
'&category=' +
selected.value +
'&q=' +
input +
'&page=' +
currentPage +
'&count=15';
const loadSearchResult = () => {
setIsLoading(true);
console.log('selected: ', selected.value);
console.log('url: ', url);
axios
.get(url)
.then((response) => {
setErrorMessage('');
console.log(response);
setTotalPages(response.data.totalPages);
if (attachEnd) {
setResultRecords([...resultRecords, ...response.data.data]);
} else {
setResultRecords(response.data.data);
}
setIsLoading(false);
setAttachEnd(false);
console.log('records: ', resultRecords);
})
.catch((error) => {
if (error.response.status == 404) {
setErrorMessage('未找到结果!');
}
setIsLoading(false);
console.log(error.response);
});
};
const onInputChange = (text) => {
if (text !== '') {
setInput(text);
console.log('onInputChange: ', input);
}
};
const renderLoader = () => {
return isLoading ? (
<View style={styles.loaderStyle}>
<ActivityIndicator size="large" color="#aaa" />
</View>
) : null;
};
//此useEffect仅执行一次该功能
useEffect(() => {
setResultRecords([]);
setInput('');
}, [navigation]);
return (
<View style={styles.container}>
<View style={styles.innerContainer}>
<AppTextInput
placeholder="搜索..."
icon="magnify"
onFieldChange={onInputChange}
/>
</View>
<View style={styles.innerContainer}>
<AppPicker
selectedItem={selected}
onSelectItem={(item) => setSelected(item)}
items={options}
icon="apps"
placeholder="类别"
/>
</View>
<View style={styles.button}>
<Button title="搜索" onPress={loadSearchResult} />
</View>
<View style={styles.results}>
{errorMessage === '' && (
<FlatList
data={resultRecords}
keyExtractor={(records) => records.title}
renderItem={({ item }) => (
<Card
title={item.title}
feedName={item.feedName}
date={item.pubDate}
imageUrl={item.image}
onPress={() => {
console.log('selectedOnPress: ', selected);
console.log('browser: ', item.link);
if (selected.value === 'news') {
navigation.navigate(
'NewsDetailsScreen',
item
);
} else if (selected.value === 'videos') {
navigation.navigate(
'YoutubeVideoDetailsScreen',
item
);
} else if (
selected.value === 'documentaries'
) {
openBrowserAsync(item.link);
} else if (selected.value === 'channels') {
openBrowserAsync(item.link);
}
}}
/>
)}
ListFooterComponent={renderLoader}
/>
)}
{errorMessage !== '' && (
<AppText style={styles.results}>{errorMessage}</AppText>
)}
</View>
</View>
);
}
const styles = StyleSheet.create({
loaderStyle: {
marginVertical: 16,
alignItems: 'center',
},
container: {
padding: 15,
paddingBottom: 50,
flexDirection: 'column',
width: '100%',
},
innerContainer: {
width: '100%',
},
button: {
width: '100%',
marginTop: 15,
marginBottom: 15,
},
results: {
marginTop: 15,
paddingBottom: 50,
textAlign: 'center',
},
});
希望这对您有所帮助。如果您有其他问题,请随时提问。
英文:
I have been searching for a while on Google but couldn't find a clear answer, my problem is that I have a search screen with a text input and a select input and button, so I click the button after entering the input text and results show after an api is called. But the issue is when I navigate to a different screen and back to the search screen the results stays. I need it to be empty the input text field and the result.
I tried many many "solutions" but none worked. I used a useEffect() hook and it did not work, tried to set the records array to empty but did not work
here is my search screen code:
import {
StyleSheet,
View,
ActivityIndicator,
FlatList,
Button,
} from 'react-native';
import React, { useState, useEffect } from 'react';
import AppTextInput from '../components/AppTextInput';
import Card from '../components/Card';
import colors from '../config/colors';
import axios from 'axios';
import { baseApiUrl, apikey } from '../api/config/apiLinks';
import AppPicker from '../components/AppPicker';
import AppText from '../components/AppText';
import { openBrowserAsync } from 'expo-web-browser';
const options = [
{ value: 'news', label: 'News' },
{ value: 'videos', label: 'Videos' },
{ value: 'documentaries', label: 'Documentaries' },
{ value: 'channels', label: 'Channels' },
];
export default function SearchScreen({ navigation }) {
const [selected, setSelected] = useState(options[0]);
const [input, setInput] = useState();
const [resultRecords, setResultRecords] = useState([]);
const [totalPages, setTotalPages] = useState();
const [currentPage, setCurrentPage] = useState(1);
const [errorMessage, setErrorMessage] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [attachEnd, setAttachEnd] = useState(false);
const url =
baseApiUrl +
'/search/search-get.php?' +
apikey +
'&category=' +
selected.value +
'&q=' +
input +
'&page=' +
currentPage +
'&count=15';
const loadSearchResult = () => {
setIsLoading(true);
console.log('selected: ', selected.value);
console.log('url: ', url);
axios
.get(url)
.then((response) => {
setErrorMessage(0);
console.log(response);
setTotalPages(response.data.totalPages);
if (attachEnd) {
setResultRecords([...resultRecords, ...response.data.data]);
} else {
setResultRecords(response.data.data);
}
setIsLoading(false);
setAttachEnd(false);
console.log('records: ', resultRecords);
})
.catch((error) => {
if (error.response.status == 404) {
setErrorMessage('Results not found!');
}
setIsLoading(false);
console.log(error.response);
});
};
const onInputChange = (text) => {
if (text != '') {
setInput(text);
console.log('onInputChange: ', input);
}
};
const renderLoader = () => {
return isLoading ? (
<View style={styles.loaderStyle}>
<ActivityIndicator size="large" color="#aaa" />
</View>
) : null;
};
//this useEffect execute the function only once
useEffect(() => {
setResultRecords([]);
setInput('');
}, [navigation]);
return (
<View style={styles.container}>
<View style={styles.innerContainer}>
<AppTextInput
placeholder="Search..."
icon="magnify"
onFieldChange={onInputChange}
/>
</View>
<View style={styles.innerContainer}>
<AppPicker
selectedItem={selected}
onSelectItem={(item) => setSelected(item)}
items={options}
icon="apps"
placeholder="Category"
/>
</View>
<View style={styles.button}>
<Button title="Search" onPress={loadSearchResult} />
</View>
<View style={styles.results}>
{errorMessage == '' && (
<FlatList
data={resultRecords}
keyExtractor={(records) => records.title}
renderItem={({ item }) => (
<Card
title={item.title}
feedName={item.feedName}
date={item.pubDate}
imageUrl={item.image}
onPress={() => {
console.log('selectedOnPress: ', selected);
console.log('browser: ', item.link);
if (selected.value == 'news') {
navigation.navigate(
'NewsDetailsScreen',
item
);
} else if (selected.value == 'videos') {
navigation.navigate(
'YoutubeVideoDetailsScreen',
item
);
} else if (
selected.value == 'documentaries'
) {
openBrowserAsync(item.link);
} else if (selected.value == 'channels') {
openBrowserAsync(item.link);
}
}}
/>
)}
ListFooterComponent={renderLoader}
/>
)}
{errorMessage != '' && (
<AppText style={styles.results}>{errorMessage}</AppText>
)}
</View>
</View>
);
}
const styles = StyleSheet.create({
loaderStyle: {
marginVertical: 16,
alignItems: 'center',
},
container: {
padding: 15,
paddingBottom: 50,
// backgroundColor: colors.light,
flexDirection: 'column',
width: '100%',
},
innerContainer: {
width: '100%',
},
button: {
width: '100%',
marginTop: 15,
marginBottom: 15,
},
results: {
marginTop: 15,
paddingBottom: 50,
textAlign: 'center',
},
});
答案1
得分: 1
你需要使用 useFocusEffect
而不是 useEffect
:
useFocusEffect(
useCallback(() => {
// 当屏幕获得焦点时执行某些操作
return () => {
// 当屏幕失去焦点时执行某些操作
// 适用于清理函数
setResultRecords([]);
setInput('');
};
}, [])
);
我建议阅读文档 https://reactnavigation.org/docs/navigation-lifecycle/
英文:
You need to use useFocusEffect
instead useEffect
:
useFocusEffect(
useCallback(() => {
// Do something when the screen is focused
return () => {
// Do something when the screen is unfocused
// Useful for cleanup functions
setResultRecords([]);
setInput('');
};
}, [])
);
I recommend read the documentation https://reactnavigation.org/docs/navigation-lifecycle/
答案2
得分: 0
你应该使用 replace
而不是 navigate
。
if (selected.value == 'news') {
navigation.replace('NewsDetailsScreen', item);
} else if (selected.value == 'videos') {
navigation.replace('YoutubeVideoDetailsScreen', item);
}
注意:
navigate
:将新路由推入堆栈。先前的路由不会被卸载。replace
:将先前的路由替换为新路由。
英文:
You should use replace
instead of navigate
.
if (selected.value == 'news') {
navigation.replace('NewsDetailsScreen', item);
} else if (selected.value == 'videos') {
navigation.replace('YoutubeVideoDetailsScreen', item);
}
Note:
navigate
: Will push the new route into the stack. The previous route won't be unmountedreplace
: Will replace the previous route with the new route.
答案3
得分: -1
你也可以使用 Promise.prototype.finally
来实现,就像这样:
const loadSearchResult = () => {
// ...
axios
.get()
.then(result => {
// ...
})
.catch(error => {
// ...
})
.finally(() => {
setText("");
})
// ...
}
英文:
You can also do it using Promise.prototype.finally
like this:
const loadSearchResult = () => {
// ...
axios
.get()
.then(result => {
// ...
})
.catch (error => {
// ...
})
.finally(() => {
setText("");
})
// ...
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论