【问题标题】:Trouble re-rendering flatlist in functional component using extraData使用 extraData 在功能组件中重新渲染平面列表时遇到问题
【发布时间】:2023-04-03 03:18:02
【问题描述】:

我正在努力重新呈现平面列表。我正在尝试使用一个布尔值refreshToggle,它被输入extraData,在成功获取所需信息后更改。下面的代码成功获取数据并更改布尔值(因此更改为状态的功能更新,虽然可能是更好的做法,但似乎不是解决方案)(我已经检查过各种日志等是否发生这种情况),但是平面列表不会重新呈现。

export default function transactions({ navigation }: { navigation: any }) {
    const [paymentsBtnActive, setPaymentsBtnActive] = React.useState<boolean>(navigation.getParam('Pressed') == 'Payments');
    const [requestsBtnActive, setRequestsBtnActive] = React.useState<boolean>(navigation.getParam('Pressed') == 'Requests');
    const [refreshToggle, setRefreshToggle] = React.useState<boolean>(false);

    let data: any[] = [];

    async function getRequests() {
        const body = { 
            'phone': GLOBAL.userInfo['phone']
        }
        const options = {
            method: 'POST',
            headers: { 'Content-Type': 'application/json'},
            body: JSON.stringify(body)
        }
        let requests =  await fetch('http://3ef68e9c1352.ngrok.io/requests/user', options);
        let requestsJSON = await requests.json();
        data = requestsJSON['data'];
    }    

    function renderItem(item: any) {
        return (<Text>{item['item']['data']['date']}</Text>)
    }
    
    function listEmpty(){
        return (<Text>Loading</Text>)
    }

    useEffect(() => {
        (async function () {
            await getRequests();
            setRefreshToggle(!refreshToggle)
        })()
    }, [])

    return (
        <SafeAreaView style = {styles.container}>
            <View style = {{flexDirection: 'row', justifyContent: 'center'}}>
                <TouchableOpacity style = { paymentsBtnActive ? styles.paymentsBtnActive : styles.paymentsBtnInactive } onPress = { () => { setRequestsBtnActive(paymentsBtnActive) 
                    setPaymentsBtnActive(!paymentsBtnActive) } } >
                    <Text style = { paymentsBtnActive ? styles.whiteText : styles.redText }>Payments</Text>
                </TouchableOpacity>
                <TouchableOpacity style = { requestsBtnActive ? styles.requestsBtnActive : styles.requestsBtnInactive } onPress = { () => { setPaymentsBtnActive(requestsBtnActive)
                    setRequestsBtnActive(!requestsBtnActive) } }  >
                    <Text style = { requestsBtnActive ? styles.whiteText : styles.redText }>Requests</Text>
                </TouchableOpacity>
            </View>


            <View style = {styles.summaryView}>
                <FlatList 
                    data={data} 
                    renderItem={renderItem} 
                    ListEmptyComponent = {listEmpty}
                    extraData = {refreshToggle}
                />
            </View>
        </SafeAreaView>
    );
    

【问题讨论】:

    标签: javascript typescript react-native expo


    【解决方案1】:

    我最终这样做了:

    export default function transactions({ navigation }: { navigation: any }) {
        const [paymentsBtnActive, setPaymentsBtnActive] = React.useState<boolean>(navigation.getParam('Pressed') == 'Payments');
        const [requestsBtnActive, setRequestsBtnActive] = React.useState<boolean>(navigation.getParam('Pressed') == 'Requests');
        const [data, setData] = React.useState<Array<any>>([]);
    
        async function getRequests() {
            const body = { 
                'phone': GLOBAL.userInfo['phone']
            }
            const options = {
                method: 'POST',
                headers: { 'Content-Type': 'application/json'},
                body: JSON.stringify(body)
            }
            let requests =  await fetch('http://3ef68e9c1976.ngrok.io/requests/user', options);
            let requestsJSON = await requests.json();
            setData(JSON.parse(JSON.stringify(requestsJSON['data'])))
        }    
    
        function renderItem(item: any) {
            console.log(item)
            return (<Text>{item['item']['data']['date']}</Text>)
        }
        
        function listEmpty(){
            return (<Text>Loading</Text>)
        }
    
        useEffect(() => {
            (async function () {
                await getRequests();
            })()
        }, [])
    
        return (
            <SafeAreaView style = {styles.container}>
                <View style = {{flexDirection: 'row', justifyContent: 'center'}}>
                    <TouchableOpacity style = { paymentsBtnActive ? styles.paymentsBtnActive : styles.paymentsBtnInactive } onPress = { () => { setRequestsBtnActive(paymentsBtnActive) 
                        setPaymentsBtnActive(!paymentsBtnActive) } } >
                        <Text style = { paymentsBtnActive ? styles.whiteText : styles.redText }>Payments</Text>
                    </TouchableOpacity>
                    <TouchableOpacity style = { requestsBtnActive ? styles.requestsBtnActive : styles.requestsBtnInactive } onPress = { () => { setPaymentsBtnActive(requestsBtnActive)
                        setRequestsBtnActive(!requestsBtnActive) } }  >
                        <Text style = { requestsBtnActive ? styles.whiteText : styles.redText }>Requests</Text>
                    </TouchableOpacity>
                </View>
    
    
                <View style = {styles.summaryView}>
                    <FlatList 
                        data={data} 
                        renderItem={renderItem} 
                        ListEmptyComponent = {listEmpty}
                    />
                </View>
            </SafeAreaView>
        );
    

    这样,当getRequests 被调用时,一个具有差异引用的新数组被分配给data,因此平面列表被重新渲染。

    因为所有数据都在变化,所以这不是需要使用 extraData 的场景,也不是设计 extraData 的场景。尽管如此,我最初的方法是受到this 的启发,但我仍然不确定为什么它不起作用。

    【讨论】:

      【解决方案2】:

      你应该改用这个

      let [data, setData] = useState<any[]>([]);
      
      const getRequests = useCallback(async function() {
         const body = {'phone': GLOBAL.userInfo['phone']}
         
         const options = {
            method: 'POST',
            headers: { 'Content-Type': 'application/json'},
            body: JSON.stringify(body)
         }
      
         let requests =  await fetch('http://3ef68e9c1352.ngrok.io/requests/user', 
         options);
      
         let requestsJSON = await requests.json();
      
         return requestsJSON['data']
      }, []);
      
      useEffect(() => {
        (async function () {
           const data = await getRequests();
           setData(data)
         })()
      }, [])
      
      
      <FlatList 
         data={data}
         renderItem={renderItem}
         ListEmptyComponent = {listEmpty}
      />
      

      【讨论】:

      • 谢谢!我可以看到为什么这会起作用,这与我解决问题的方式非常相似。如果我理解正确,两者本质上都是有效的,因为当调用getRequests 时,数据会使用具有不同引用的新数组进行更新。我仍然不确定为什么我无法使用extraData 方法(尽管我现在明白了,因为所有数据都在变化,这并不是真正需要使用extraData 的场景,也不是 extraData 的预期场景)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-09
      • 2017-09-09
      • 2020-10-31
      • 2020-08-10
      • 1970-01-01
      • 2020-03-18
      • 2010-11-02
      相关资源
      最近更新 更多