清空搜索屏幕后导航到不同屏幕

huangapple go评论62阅读模式
英文:

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 &#39;react-native&#39;;
import React, { useState, useEffect } from &#39;react&#39;;
import AppTextInput from &#39;../components/AppTextInput&#39;;
import Card from &#39;../components/Card&#39;;

import colors from &#39;../config/colors&#39;;

import axios from &#39;axios&#39;;
import { baseApiUrl, apikey } from &#39;../api/config/apiLinks&#39;;
import AppPicker from &#39;../components/AppPicker&#39;;
import AppText from &#39;../components/AppText&#39;;
import { openBrowserAsync } from &#39;expo-web-browser&#39;;

const options = [
    { value: &#39;news&#39;, label: &#39;News&#39; },
    { value: &#39;videos&#39;, label: &#39;Videos&#39; },
    { value: &#39;documentaries&#39;, label: &#39;Documentaries&#39; },
    { value: &#39;channels&#39;, label: &#39;Channels&#39; },
];

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(&#39;&#39;);
    const [isLoading, setIsLoading] = useState(false);
    const [attachEnd, setAttachEnd] = useState(false);

    const url =
        baseApiUrl +
        &#39;/search/search-get.php?&#39; +
        apikey +
        &#39;&amp;category=&#39; +
        selected.value +
        &#39;&amp;q=&#39; +
        input +
        &#39;&amp;page=&#39; +
        currentPage +
        &#39;&amp;count=15&#39;;

    const loadSearchResult = () =&gt; {
        setIsLoading(true);
        console.log(&#39;selected: &#39;, selected.value);
        console.log(&#39;url: &#39;, url);

        axios
            .get(url)
            .then((response) =&gt; {
                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(&#39;records: &#39;, resultRecords);
            })
            .catch((error) =&gt; {
                if (error.response.status == 404) {
                    setErrorMessage(&#39;Results not found!&#39;);
                }
                setIsLoading(false);
                console.log(error.response);
            });
    };

    const onInputChange = (text) =&gt; {
        if (text != &#39;&#39;) {
            setInput(text);
            console.log(&#39;onInputChange: &#39;, input);
        }
    };

    const renderLoader = () =&gt; {
        return isLoading ? (
            &lt;View style={styles.loaderStyle}&gt;
                &lt;ActivityIndicator size=&quot;large&quot; color=&quot;#aaa&quot; /&gt;
            &lt;/View&gt;
        ) : null;
    };

    //this useEffect execute the function only once
    useEffect(() =&gt; {
        setResultRecords([]);
        setInput(&#39;&#39;);
    }, [navigation]);

    return (
        &lt;View style={styles.container}&gt;
            &lt;View style={styles.innerContainer}&gt;
                &lt;AppTextInput
                    placeholder=&quot;Search...&quot;
                    icon=&quot;magnify&quot;
                    onFieldChange={onInputChange}
                /&gt;
            &lt;/View&gt;
            &lt;View style={styles.innerContainer}&gt;
                &lt;AppPicker
                    selectedItem={selected}
                    onSelectItem={(item) =&gt; setSelected(item)}
                    items={options}
                    icon=&quot;apps&quot;
                    placeholder=&quot;Category&quot;
                /&gt;
            &lt;/View&gt;
            &lt;View style={styles.button}&gt;
                &lt;Button title=&quot;Search&quot; onPress={loadSearchResult} /&gt;
            &lt;/View&gt;

            &lt;View style={styles.results}&gt;
                {errorMessage == &#39;&#39; &amp;&amp; (
                    &lt;FlatList
                        data={resultRecords}
                        keyExtractor={(records) =&gt; records.title}
                        renderItem={({ item }) =&gt; (
                            &lt;Card
                                title={item.title}
                                feedName={item.feedName}
                                date={item.pubDate}
                                imageUrl={item.image}
                                onPress={() =&gt; {
                                    console.log(&#39;selectedOnPress: &#39;, selected);
                                    console.log(&#39;browser: &#39;, item.link);
                                    if (selected.value == &#39;news&#39;) {
                                        navigation.navigate(
                                            &#39;NewsDetailsScreen&#39;,
                                            item
                                        );
                                    } else if (selected.value == &#39;videos&#39;) {
                                        navigation.navigate(
                                            &#39;YoutubeVideoDetailsScreen&#39;,
                                            item
                                        );
                                    } else if (
                                        selected.value == &#39;documentaries&#39;
                                    ) {
                                        openBrowserAsync(item.link);
                                    } else if (selected.value == &#39;channels&#39;) {
                                        openBrowserAsync(item.link);
                                    }
                                }}
                            /&gt;
                        )}
                        ListFooterComponent={renderLoader}
                    /&gt;
                )}
                {errorMessage != &#39;&#39; &amp;&amp; (
                    &lt;AppText style={styles.results}&gt;{errorMessage}&lt;/AppText&gt;
                )}
            &lt;/View&gt;
        &lt;/View&gt;
    );
}

const styles = StyleSheet.create({
    loaderStyle: {
        marginVertical: 16,
        alignItems: &#39;center&#39;,
    },
    container: {
        padding: 15,
        paddingBottom: 50,
        // backgroundColor: colors.light,
        flexDirection: &#39;column&#39;,
        width: &#39;100%&#39;,
    },
    innerContainer: {
        width: &#39;100%&#39;,
    },
    button: {
        width: &#39;100%&#39;,
        marginTop: 15,
        marginBottom: 15,
    },
    results: {
        marginTop: 15,
        paddingBottom: 50,
        textAlign: &#39;center&#39;,
    },
});

答案1

得分: 1

你需要使用 useFocusEffect 而不是 useEffect

  useFocusEffect(
    useCallback(() => {
      // 当屏幕获得焦点时执行某些操作

      return () => {
        // 当屏幕失去焦点时执行某些操作
        // 适用于清理函数
        setResultRecords([]);
        setInput('');
      };
    }, [])
  );

我建议阅读文档 https://reactnavigation.org/docs/navigation-lifecycle/

英文:

You need to use useFocusEffect instead useEffect:

  useFocusEffect(
    useCallback(() =&gt; {
      // Do something when the screen is focused

      return () =&gt; {
        // Do something when the screen is unfocused
        // Useful for cleanup functions
        setResultRecords([]);
        setInput(&#39;&#39;);
      };
    }, [])
  );

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 == &#39;news&#39;) {
navigation.replace(&#39;NewsDetailsScreen&#39;, item);
} else if (selected.value == &#39;videos&#39;) {
navigation.replace(&#39;YoutubeVideoDetailsScreen&#39;, item);
}

Note:

  • navigate: Will push the new route into the stack. The previous route won't be unmounted
  • replace: 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 = () =&gt; {
// ...
axios
.get()
.then(result =&gt; { 
// ...
})
.catch (error =&gt; { 
// ... 
})
.finally(() =&gt; {
setText(&quot;&quot;);
})
// ...
}  

huangapple
  • 本文由 发表于 2023年5月21日 16:11:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76298896.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定