我有一个用expo构建的react-native应用程序。
这是一个预算应用程序。我正在尝试显示给定月份支出类型的饼图。
我的逻辑如下:
- 通过 dispatch(( in useEffect 从 redux 检索支出
- 将支出与其他字段一起推送到将提供给饼图的数组。
- 以该数组作为道具供应到饼图。
我正在经历什么:
- 使用 中通过 dispatch(( 从 redux 检索支出效果
- 尝试将其他字段的支出推送到数据数组。
- 尝试将此数组提供给饼图。
- 饼图呈现为完全空白。(此时记录数组显示它也为空(
- (在 useEffect 钩子中记录数组显示非空数组(
我的代码:
import React, {useEffect} from 'react';
import { StyleSheet, StatusBar, View, Text, AsyncStorage, Button, Dimensions } from 'react-native';
import {useSelector,useDispatch} from 'react-redux';
import {getExp, clearExp} from './../actions/expActions.js';
import _uniqueId from 'lodash/uniqueId';
import { getRecurrExp } from '../actions/recurrExpActions.js';
import { PieChart } from "react-native-chart-kit";
export default function Report() {
const expR = useSelector(state => state.expR)
const recurrExpR = useSelector(state => state.recurrExpR)
const dispatch = useDispatch();
const screenWidth = Dimensions.get("window").width
const chartConfig ={
backgroundColor: "#e26a00",
backgroundGradientFrom: "#fb8c00",
backgroundGradientTo: "#ffa726",
decimalPlaces: 2, // optional, defaults to 2dp
color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
labelColor: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
style: {
borderRadius: 16
},
propsForDots: {
r: "6",
strokeWidth: "2",
stroke: "#ffa726"
}
}
var piePieces = [];
const getAllExps = () => {
dispatch(getExp())
dispatch(getRecurrExp())
}
useEffect(() => {
getAllExps()
expR.catCounts.map(cat => {
piePieces.push({value: cat.count / expR.cat * 100, name: cat.category, color: cat.category==="cat1" ? '#E38627' : '#C13C37' })
})
console.log(piePieces) //Log's a filled array
},[])
// Deprecated, saving for
const clearAsyncStorage = async() => {
AsyncStorage.clear()
}
const clearExpTest = () => {
dispatch(clearExp())
}
return (
<View style={styles.main}>
<View style={styles.container}>
<StatusBar hidden />
{
<PieChart
data={piePieces}
width={220}
height={220}
chartConfig={chartConfig}
accessor="value"
backgroundColor="transparent"
paddingLeft="15"
absolute
/>
}
{console.log(piePieces)} //Logs []
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
backgroundColor: '#ffffe6',
},
main: {
flex: 1,
}
});
我的猜测是这与重新渲染组件有关。由于您正在推送到piePieces
而不是重新分配,因此不会重新渲染。
我还建议使用Sate for piePieces来规避这个确切的问题。
将 useState 添加到导入
import React, {useEffect, useState} from 'react';
组件顶部定义饼图件
const [piePieces, setPiePiecse] = useState([]);
您可以使用forEach
而不是map
因为 map 返回一个包含返回值的新数组
expR.catCounts.forEach(cat => {
setPiePieces([...piePieces, {value: cat.count / expR.cat * 100, name: cat.category, color: cat.category==="cat1" ? '#E38627' : '#C13C37' }])
})
对于将来的任何人,Bloatlords 的答案是正确的,但会导致在每个循环中设置状态的异步问题。
为了解决这个问题,设置状态的正确方法是:
setPiePieces(piePieces => [...piePieces, {value: ((cat.count / expR.cat) * 100),
name: cat.category,
color: (cat.category.localeCompare("cat1") ? "green" : "yellow"),
legendFontColor: "black", legendFontSize: 15}
])