I have a question regarding useState.
When I create a usestate like this => const [dataChart, setDataChart] = useState(dataState()); Suddenly an error message appears in the console (Uncaught ReferenceError: Cannot access 'dataState' before initialization)
Why is that about and what solution can you give me? Thank you
MyCode =
const [filterdata, setFilterdata] = useState([]);
const [query, setQuery] = useState("");
const [dataProvinsi, setDataProvinsi] = useState([]);
const [dataKota, setDataKota] = useState([]);
const [dataKecamatan, setDataKecamatan] = useState([]);
const [dataKelurahan, setDataKelurahan] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [isLoadingKota, setIsLoadingKota] = useState(false);
const [isLoadingKecamatan, setIsLoadingKecamatan] = useState(false);
const [selectedValue, setSelectedValue] = useState("");
const [dataChart, setDataChart] = useState(dataState());
const provinsiRef = useRef([]);
const kotaRef = useRef([]);
const kecamatanRef = useRef([]);
const getDataAllProvinsi = () => {
setIsLoading(true);
getStreetDallProvinsi()
.then((resolve) => {
setDataProvinsi(resolve);
setFilterdata(resolve);
console.log(resolve);
})
.catch((reject) => {
console.log(reject);
})
.finally(setIsLoading(false));
};
const handlesearch = (event) => {
const getSearch = event.target.value;
if (getSearch.length > 0) {
const searchdata = dataProvinsi.filter((item) =>
item.provinsi.toLowerCase().includes(event.target.value.toLowerCase())
);
setDataProvinsi(searchdata);
} else {
setDataProvinsi(filterdata);
}
setQuery(getSearch);
};
const handleProvinsi = async (index) => {
try {
const provinsi = provinsiRef.current[index].dataset.prov;
setIsLoading(true);
const result = await getStreetallKota(provinsi);
setDataKota(result);
console.log(result);
} catch (error) {
console.log("salah");
} finally {
setIsLoading(false);
}
};
const handleKota = async (provinsi, index) => {
try {
const kota = kotaRef.current[index].dataset.city;
setIsLoadingKota(true);
const result = await getStreetallKecamatan(provinsi, kota);
setDataKecamatan(result);
console.log(result);
} catch (error) {
console.log("salah");
} finally {
setIsLoadingKota(false);
}
};
const handleKecamatan = async (provinsi, kota, index) => {
try {
const kecamatan = kecamatanRef.current[index].dataset.camat;
setIsLoadingKecamatan(true);
const result = await getStreetallKelurahan(provinsi, kota, kecamatan);
setDataKelurahan(result);
console.log(result);
} catch (error) {
console.log("salah");
console.log(error);
} finally {
setIsLoadingKecamatan(false);
}
};
useEffect(() => {
getDataAllProvinsi();
}, []);
const colorCode = "#0066FF";
const colorFont = "#8E9093";
const dataState = () => ({
data: {
dataProv: {
labels: dataProvinsi.map((o) => o.provinsi),
datasets: [
{
fill: true,
label: null,
backgroundColor: colorCode,
borderColor: colorCode,
borderWidth: 2,
borderRadius: 12,
data: dataProvinsi.map((o) => o.total_street),
},
],
},
dataKota: {
labels: dataKota.map((o) => o.kota),
datasets: [
{
fill: true,
label: null,
backgroundColor: colorCode,
borderColor: colorCode,
borderWidth: 2,
borderRadius: 12,
data: dataKota.map((o) => o.total_street),
},
],
},
dataKecamatan: {
labels: dataKecamatan.map((o) => o.kecamatan),
datasets: [
{
fill: true,
label: null,
backgroundColor: colorCode,
borderColor: colorCode,
borderWidth: 2,
borderRadius: 12,
data: dataKecamatan.map((o) => o.total_street),
},
],
},
},
options: {
plugins: {
legend: {
display: false,
labels: {
font: {
color: colorFont,
},
},
},
},
scales: {
x: {
grid: {
display: false,
},
beginAtZero: false,
ticks: {
color: colorFont,
},
},
y: {
grid: {
display: false,
},
beginAtZero: true,
ticks: {
color: colorFont,
},
},
},
},
});
const plugins = [
{
beforeDraw: function (chart) {
if (chart.chartArea) {
let ctx = chart.ctx;
let chartArea = chart.chartArea;
let barArray = chart.getDatasetMeta(0).data;
ctx.fillStyle = "#B2D1FF85";
for (let i = 0; i < barArray.length; i ) {
const { x, width } = barArray[i];
ctx.fillRect(
x - width / 2,
chartArea.top,
width,
chartArea.bottom - chartArea.top
);
}
}
},
},
];
useEffect(() => {
setDataChart(dataState());
}, [selectedValue]);
CodePudding user response:
You're making a call to dataState() method in your initialization well before it's defined (notice how dataState is declared something like 50 lines below where you're calling it). dataState as an undefined variable can't be invoked. Either put the definition for dataState before your useState invocation, use a better initial state for dataChart, or as it appears to me, dataChart can be derived from your other state variables and thus should not be a separate state.
CodePudding user response:
the issue is in the error message itself, 'Uncaught ReferenceError: Cannot access 'dataState' before initialization'. you are trying to use dataState
function before its declaration. quick solution is you can get the dataState
function to outside of the component itself and declare it above the file.
and to use it as the state, your function should return something out of it also. and here you've violated the state management also. I would suggest you move the dataState function inside a useMemo
hook. like this, if it's calculating anything using any state variables from props, otherwise I don't see a point to assign those values to another state also.
const dataChart = useMemo(() => ({
data: {
dataProv: {
labels: dataProvinsi.map((o) => o.provinsi),
datasets: [
{
fill: true,
label: null,
backgroundColor: colorCode,
borderColor: colorCode,
borderWidth: 2,
borderRadius: 12,
data: dataProvinsi.map((o) => o.total_street),
},
],
},
dataKota: {
labels: dataKota.map((o) => o.kota),
datasets: [
{
fill: true,
label: null,
backgroundColor: colorCode,
borderColor: colorCode,
borderWidth: 2,
borderRadius: 12,
data: dataKota.map((o) => o.total_street),
},
],
},
dataKecamatan: {
labels: dataKecamatan.map((o) => o.kecamatan),
datasets: [
{
fill: true,
label: null,
backgroundColor: colorCode,
borderColor: colorCode,
borderWidth: 2,
borderRadius: 12,
data: dataKecamatan.map((o) => o.total_street),
},
],
},
},
options: {
plugins: {
legend: {
display: false,
labels: {
font: {
color: colorFont,
},
},
},
},
scales: {
x: {
grid: {
display: false,
},
beginAtZero: false,
ticks: {
color: colorFont,
},
},
y: {
grid: {
display: false,
},
beginAtZero: true,
ticks: {
color: colorFont,
},
},
},
},
}), [])
CodePudding user response:
You should return something in the dataState
to assign it to a useState
.
useState
is used to provide some value to a state so it must receive some value from the dataState
function.