使用 extraData 在功能组件中重新渲染平面列表时遇到问题

时间:2021-01-31 10:47:57

标签: javascript typescript react-native expo

我正在努力重新渲染平面列表。我正在尝试使用一个布尔值 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>
    );
    

2 个答案:

答案 0 :(得分:0)

你应该用这个代替

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}
/>

答案 1 :(得分:0)

我最终这样做了:

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,以便重新渲染 Flatlist。

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