在React中更新嵌套状态setState

时间:2018-09-24 17:56:37

标签: reactjs state

无法弄清楚为什么此状态将不会更新,因此嵌套了除personalValues之外的其他值。

状态

this.state = {
   personalValues: [
     {targetLevel: 0},
     {firstCommission: 0.36},
     {cancels: 0.10},
     {averagePolicy: 1150},
     {productionWeeks: 48},
     {presPerWeek: 15},
     {closingRate: 0.40},
     {appsPerWeek: 6}
   ]

我尝试过的处理程序

handleFormChange(event){
  this.setState({[event.target.name]: event.target.value})
}

组件

const personalFormValues =
    { 
      class: ["firstCommission", "cancels", "averagePolicy",
              "productionWeeks", "presPerWeek", "closingRate",
              "appsPerWeek"],
    };
var className = personalFormValues.class[i];   
    <TextField
                className={className}
                type="number"
                placeholder={personalFormValues.placeholder[i]}
                onChange={this.handleFormChange}
                onBlur={this.changeValues}
                name={className}
                fullWidth={true}
                pattern="[0-9]*"
                required />

4 个答案:

答案 0 :(得分:1)

就状态而言,只有一个值this.state.personalValues。对于React,该值是否是对象数组并不重要。相反,只需创建一个存储当前值let obj = this.state.personalValues的变量。然后遍历obj,直到找到与event.target.name匹配的键,并将该obj的值设置为event.target.value。或更简单地说,不使用数组而是直接使用对象:

this.state = {
   personalValues: {
     targetLevel: 0,
     firstCommission: 0.36,
     cancels: 0.10,
     averagePolicy: 1150,
     productionWeeks: 48,
     presPerWeek: 15,
     closingRate: 0.40,
     appsPerWeek: 6
   }

那你可以做:

let obj = this.state.personalValues;
obj[event.target.name] = event.target.value;
this.setState({personalValues: obj});

答案 1 :(得分:0)

您是否需要personalValues作为数组?如果您这样指定,那应该可以:

state = {
  personalData: {
    targetLevel: 0,
    firstCommission: 0.36
    ....
  }
}

handleFormChange({target}){
  this.setState(prevState => ({
    personalValues: {
      ...prevState.personalValues,
      [target.name]: target.value
    }
  })
}

答案 2 :(得分:0)

将旧状态复制到新变量,然后根据需要更改值,然后使用新创建的类型变量更新状态值的更好方法。

public IActionResult PickAlert(Alert obj, int? SelectedAlertIndex)
    {
        if (SelectedAlertIndex.HasValue)
        {
            ViewBag.Message = "Alert loaded successfully";
        }
        return View(_context.Alert.Where(x => x.AlertIndex == SelectedAlertIndex));
    }

答案 3 :(得分:0)

React在触发重新渲染之前检查this.state的元素是否具有浅指针等效性。 因此,如果就地修改递归数据结构,那么React不会注意到变化,因为前一个状态对象与下一个状态对象之间的浅层比较没有区别。

因此,您不能写递归结构,也不能:

this.setState(prevState => ({personalValues: Object.assign(prevState.personalValues, nextValues)}));

因为Object.assign执行就地修改。

您必须执行以下任一操作:

this.setState(prevState => ({personalValues: Object.assign({}, prevState.personalValues, nextValues)}));
this.setState(prevState => ({personalValues: {...prevState.personalValues, ...nextValues}}));

这将创建一个新对象并在其中复制数据结构。请注意,仅重新创建了一级对象。 递归复制变得难看;参见https://stackoverflow.com/a/43041334/1235724

尽管如此,如果您的state中存储的数据结构非常大, 您可能要与this.forceUpdate()一起使用就地修改, 完全避免复制。