React问题:Props变更时孙组件未重新渲染值
问题解决:费率类型变更时已选员工费率不更新
问题根源
你的Breakdown组件仅在组件挂载和选择员工类型时调用updateRate计算费率,但当父组件传递的rateType props发生变化时,组件没有监听这个变更并重新计算费率,导致已选中员工的费率无法同步更新。
解决方案
添加componentDidUpdate生命周期函数,监听rateType props的变化,一旦检测到变更就重新执行updateRate,更新当前员工的费率:
// 在组件中添加以下生命周期函数 componentDidUpdate(prevProps) { // 仅当rateType发生变化时执行更新 if (prevProps.rateType !== this.props.rateType) { this.updateRate(); } }
完整修改后的组件代码
import React, { Component } from 'react'; import {Form} from 'react-bootstrap'; import styled from 'styled-components'; import { config } from '../../Config/Constants'; import debounce from 'lodash.debounce'; const API_URL = config.url.API_URL; const Div = styled.div` color: black; ` class Breakdown extends Component { constructor(props) { super(props); this.state = { employee_type: "Choose", employee_name: "Choose", rate: 0, cost: 0, hours1: 0, hours2: 0, hours3: 0, total_hours: 0, total_costs: 0, total_bill: 0, margin: 0, // Cost Chart employeeTable: [ { name: "Choose", cost: 0, type:"Choose"}, { name: "Adam N", cost: 95.53, type: "Executive" }, { name: "Amber H", cost: 50.33, type: "Senior" }, { name: "Denise M", cost: 28.34, type: "Coordinator" } ], // Rate Charts rateChartNonProfit: [ { type: "Choose", rate: 0 }, { type: "Executive", rate: 300 }, { type: "Senior", rate: 250 }, { type: "Mid-Level", rate: 200 }, { type: "Associate", rate: 150 }, { type: "Coordinator", rate: 150 } ], rateChartForProfit: [ { type: "Choose", rate: 0 }, { type: "Executive", rate: 400 }, { type: "Senior", rate: 275 }, { type: "Mid-Level", rate: 225 }, { type: "Associate", rate: 175 }, { type: "Coordinator", rate: 175 } ], rateChartExisting: [ { type: "Choose", rate: 0 }, { type: "Executive", rate: 400 }, { type: "Senior", rate: 275 }, { type: "Mid-Level", rate: 225 }, { type: "Associate", rate: 175 }, { type: "Coordinator", rate: 175 } ] } } componentDidMount() { this.getBreakdownData(this.props.breakdownId); } // 添加这个生命周期函数 componentDidUpdate(prevProps) { if (prevProps.rateType !== this.props.rateType) { this.updateRate(); } } getBreakdownData(breakdownId) { fetch(API_URL + `/billingcalculator/${breakdownId}`) .then((res) => { if (!res.ok) { throw new Error() } return res.json() }) .then((result) => { this.setState({ ...result[0], }); }) .catch((error) => { console.log(error); }) .then(() => this.updateRate()); // 修正异步调用问题 } selectType = (e) => { this.setState({ employee_type: e.target.value }, () => this.updateRate() ) } selectEmployee = (e) => { // 补充缺失的员工选择逻辑,更新对应成本 const selectedEmployee = this.state.employeeTable.find(emp => emp.name === e.target.value); this.setState({ employee_name: e.target.value, cost: selectedEmployee?.cost || 0 }); } handleChange = (e) => { // 补充缺失的工时输入逻辑,更新工时并计算总工时 const { name, value } = e.target; this.setState({ [name]: parseFloat(value) || 0 }, () => { this.updateTotals(); }); } updateRate() { let rateType = this.props.rateType; let targetChart; // 简化费率表选择逻辑 switch(rateType) { case "non-profit": targetChart = this.state.rateChartNonProfit; break; case "existing": targetChart = this.state.rateChartExisting; break; default: targetChart = this.state.rateChartForProfit; } const matchedRate = targetChart.find(item => item.type === this.state.employee_type); this.setState({ rate: matchedRate?.rate || 0 }, () => this.updateTotals()); } updateTotals() { // 补充缺失的计算逻辑,计算总工时、成本、账单和利润 const { hours1, hours2, hours3, rate, cost } = this.state; const totalHours = hours1 + hours2 + hours3; const totalCosts = totalHours * cost; const totalBill = totalHours * rate; const margin = totalBill - totalCosts; this.setState({ total_hours: totalHours, total_costs: totalCosts, total_bill: totalBill, margin: margin }); } render() { return ( <tr key={this.props.breakdownId}> <td> <select name="employee_type" value={this.state.employee_type} onChange={this.selectType}> <option value="Choose">Choose</option> <option value="Executive">Executive</option> <option value="Senior">Senior</option> <option value="Mid-Level">Mid-Level</option> <option value="Associate">Associate</option> <option value="Coordinator">Coordinator</option> </select> </td> <td> <select name="employee_name" value={this.state.employee_name} onChange={this.selectEmployee}> <option value="Choose">Choose</option> <option value="Adam N">Adam N</option> <option value="Amber H">Amber H</option> <option value="Denise M">Denise M</option> </select> </td> <td> {this.state.rate} </td> <td> {this.state.cost} </td> <td> <Form.Control size="sm" type="text" value={this.state.hours1} onChange={this.handleChange} name="hours1" /> </td> <td> <Form.Control size="sm" type="text" value={this.state.hours2} onChange={this.handleChange} name="hours2" /> </td> <td> <Form.Control size="sm" type="text" value={this.state.hours3} onChange={this.handleChange} name="hours3" /> </td> <td> {this.state.total_hours} </td> <td> {this.state.total_costs} </td> <td> {this.state.total_bill} </td> <td> {this.state.margin} </td> </tr> ) } } export default Breakdown;
额外优化说明
- 修复了
getBreakdownData中异步调用updateRate的错误写法,避免函数立即执行 - 补充了原代码缺失的
selectEmployee、handleChange、updateTotals函数,保证功能完整性 - 简化了
updateRate中的费率表选择逻辑,提升代码可读性和维护性
内容的提问来源于stack exchange,提问作者Adam Norton
相关产品推荐
相关产品推荐

