[英]Component doesn't re-render after I set state
我正在嘗試在 React 中構建一個迷你項目,它是一個 BMI 跟蹤器,用戶輸入他的體重和身高,然后程序計算 BMI,每當應用程序從用戶那里收到數據(身高和體重)時,它就代表結果和用戶在圖表中輸入該數據的日期。 為此,我制作了三個組件,第一個是InputContainer
組件,在其中執行計算。
import React, { useState, useRef, useEffect } from 'react';
import Graph from '../Graph/Graph';
import Logs from '../Logs/logs';
import './InputContainer.scss';
let date;
let currentDate;
let dates = []
let bmiResults = []
let dataLog = [];
export default function InputContainer() {
const [result, setBmiResult] = useState('');
const [height, setHeight] = useState('');
const [weight, setWeight] = useState('');
const [bmiAxis,setBmiAxis] = useState('');
const [dateAxis,setDateAxis] = useState('');
const calculateButton = useRef(null);
const firstUpdate = useRef(true);
useEffect(() => {
date = new Date();
currentDate = `${date.getDate()}/${date.getMonth()}/${date.getFullYear()}`
calculateButton.current.disabled = isNaN(parseFloat(height) && parseFloat(weight)) ? true : false;
}, [height, weight]);
useEffect(() => {
if (firstUpdate.current) {
firstUpdate.current = false;
return
}
let dataLogElement = <div className="test">
<div className="bmi-and-date">
<p className="bmi">
BMI: {result}
</p>
<p className="date">
Date: {currentDate}
</p>
</div>
<div className="height-and-weight">
<p className="height">
Height: {height}
</p>
<p className="weight">
weight: {weight}
</p>
</div>
</div>;
dataLog.push(dataLogElement);
dates.push(currentDate);
bmiResults.push(result);
setBmiAxis(bmiResults);
setDateAxis(dates);
}, [result])
const calculate = () => {
let bmi = (parseFloat(weight) / parseFloat(height) ** 2).toFixed(2)
setBmiResult(parseFloat(bmi))
}
return (
<>
<div className='input-container'>
<h1>BMI Tracker</h1>
<div className="input">
<div className="height">
<h3>Enter Your Height in CM</h3>
<input type="number" onChange={(e) => {
setHeight(e.target.value)
}} value={height} />
</div>
<div className="weight">
<h3>Enter Your Weight in Kg</h3>
<input type="number" onChange={(e) => {
setWeight(e.target.value)
}} />
</div>
</div>
<button className='calculate' onClick={calculate} ref={calculateButton}>Calculate</button>
</div>
<Graph bmi={result} date={currentDate} dates={dateAxis} results={bmiAxis} />
<Logs element = {dataLog}/>
</>
)
}
第二個組件是Graph
組件,它從 props 接收用戶的數據,然后將其顯示在圖表中:
import React from 'react'
import { Line } from 'react-chartjs-2';
import './Graph.scss'
export default function Graph(props) {
const data = {
labels: props.dates,
datasets: [
{
label: 'BMI',
data: props.results,
fill: 'origin',
backgroundColor: '#16a5e1',
pointBackgroundColor: '#16a5e1',
pointBorderColor: 'blue',
pointRadius: '4'
},
],
};
const options = {
tension: 0.4,
scales: {
y: {
ticks: {
color: 'white'
},
beginAtZero: true
},
x: {
ticks: {
color: 'white'
},
}
}
};
return (
<div className='graph-container'>
<Line data={data} options={options} />
</div>
)
}
然后是第三個組件Logs
組件,它在頁面的按鈕處顯示每個用戶提交的詳細信息
import React from 'react'
import './logs.scss'
export default function Logs(props) {
return (
<div className='logs-container'>
{props.element}
</div>
)
}
啟動應用程序后,我輸入體重和身高,然后單擊calculate
按鈕,數據成功繪制到圖表中,其相應的詳細信息記錄在頁面底部,這正是我想要的,但問題是是用戶輸入的數據僅在第一次輸入時成功顯示,當我第二次輸入數據時,后台計算正確完成並計算第二次輸入的結果,但屏幕上沒有任何變化,並且我只能看到第一個條目的結果,然后一旦我開始為第三個條目輸入數據,我就會得到第一個的結果以及我之前輸入的第二個條目顯示在屏幕上,結果只在我開始時顯示為下一個條目輸入數據,而不是在單擊calculate
按鈕后立即輸入。 這是我想要實現的一個例子:
如果你想在你的機器上測試它,這里有一個 repo 的鏈接: https : //github.com/Marouane328/Bmi-tracker
在 Graph 中,您是否可以考慮將const data
和const options
轉換為狀態,並使用 useEffect 將 props 值分配給狀態,從而使 props 依賴於 useEffect。
試試這個它在你的代碼和盒子( https://codesandbox.io/s/peaceful-hofstadter-onso9 )的回購中工作:
const [data, setData] = React.useState({
labels: props.dates,
datasets: [
{
label: 'BMI',
data: props.results,
fill: 'origin',
backgroundColor: '#16a5e1',
pointBackgroundColor: '#16a5e1',
pointBorderColor: 'blue',
pointRadius: '4'
},
],
});
const [options, setOptions] = React.useState({
tension: 0.4,
scales: {
y: {
ticks: {
color: 'white'
},
beginAtZero: true
},
x: {
ticks: {
color: 'white'
},
}
}
});
React.useEffect(
()=>{
setData({
labels: props.dates,
datasets: [
{
label: 'BMI',
data: props.results,
fill: 'origin',
backgroundColor: '#16a5e1',
pointBackgroundColor: '#16a5e1',
pointBorderColor: 'blue',
pointRadius: '4'
},
],
});
setOptions({
tension: 0.4,
scales: {
y: {
ticks: {
color: 'white'
},
beginAtZero: true
},
x: {
ticks: {
color: 'white'
},
}
}
});
},[props]
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.