简体   繁体   English

React - 如何根据道具更改多个初始状态

[英]React - How can I change multiple initial states based on the props

I am a newbie to React.我是 React 的新手。 I came up with a question about my code.我想出了一个关于我的代码的问题。 I cannot initialize the state based on the props.我无法根据道具初始化 state。 For example, I can get the jsonData(in NCMenuItems class) value, but when I try to initialize other states like groups, showpin, direction, isCollapsible based on the jsonData value, React always gives me an error saying that these states are null.例如,我可以获得 jsonData(在 NCMenuItems 类中)值,但是当我尝试根据jsonData值初始化其他状态(如组、showpin、direction、 isCollapsible )时,React 总是给我一个错误,说这些状态是 null。

Also, I find another problem, the console.log in render() in NCMenuItems class always print twice, why is that?另外,我发现另一个问题,NCMenuItems class 中的render()中的console.log总是打印两次,这是为什么呢? Thank you so much.太感谢了。

Here is my code:这是我的代码:

NCMenuItems class NCMenuItems class

import React, {Component} from 'react';
import NCMenuItem from '../MenuComponent/NCMenuItem';

class NCMenuItems extends Component {
state = {
    jsonData: this.props.jSONObj,
    showpin: false,
    direction: false,
    isCollapsible: false,
    cssFilePath: '',
    groups: null
};

static getDerivedStateFromProps(props, state){
    return {
        showpin: this.state.jsonData.showpin === '1'? true:false,
        direction: this.state.jsonData.direction === '1'? true:false,
        isCollapsible: this.state.jsonData.isCollapsible === '1'? true:false,
        cssFilePath: this.state.jsonData.cssFilePath,
        groups: this.state.jsonData.groups
    }
}


render() {
    console.log('From NCMenuItems this.props.jSONObj',this.props.jSONObj);
    console.log('From NCMenuItems this.state.jsonData',this.state.jsonData);
    console.log('From NCMenuItems this.state.groups',this.state.groups);
    console.log('From NCMenuItems this.state.jsonData.groups',this.state.jsonData.groups);
    return (
    <div>
        <ul id="nc-menu-ul" showpin direction isCollapsible cssFilePath={this.state.isCollapsible}>
            {/* <NCMenuItem groups={this.state.groups}/> */}
        </ul>
    </div>
    );
}
}

export default NCMenuItems;

In App.js在 App.js 中

import React, { Component } from 'react';
import NCMenuItems from './MenuComponent/NCMenuItems';

class App extends Component {
constructor(props) {
super(props);
this.state = {
  deserializedJSONObj: {
    nc_menu_parameters: {
      showPin: 1,
      direction: 1,
      isCollapsible: 1,
      cssFilePath: ""
    },
    nc_menu_groups: [
      {
        label: "Project",
        nc_menu_entries: [
          { entryLabel: "Overview", entryLink: "/Details", isClickable: 1 },
          { entryLabel: "Comments", entryLink: "/Comments", isClickable: 1 },
          { entryLabel: "Activity", entryLink: "/Activity", isClickable: 1 },
          { entryLabel: "Multiplier", entryLink: "/Multiplier", isClickable: 1 }
        ]
      },
      {
        label: "Heaters",
        nc_menu_entries: [
          {
            entryLabel: "In design",
            entryLink: "/InDesignParts",
            isClickable: 1
          },
          { entryLabel: "Parts", entryLink: "/InDesignParts", isClickable: 1 },
          {
            entryLabel: "Pricing",
            entryLink: "/InDesignPricing",
            isClickable: 1
          },
          {
            entryLabel: "Documents",
            entryLink: "/InDesignDocument",
            isClickable: 1
          }
        ]
      }
    ]
  }
};
}


 render() {
console.log('FROM App.js', this.state.deserializedJSONObj);
return (
  <div>
    <NCMenuItems jSONObj={this.state.deserializedJSONObj} />{/* pass the JSON object as props to NCMenuItems*/}
    <h1>Test the nc_menu!</h1>
  </div>
);
}
}

export default App;

The render is triggered twice because the first render happens on mount, the second re-render happens when getDerivedStateFromProps is called - which sets state again and triggers a rerender.渲染被触发两次,因为第一次渲染发生在挂载时,第二次重新渲染发生在调用 getDerivedStateFromProps 时 - 再次设置getDerivedStateFromProps并触发重新渲染。

Regarding your question, you need to look at props.jsonData , not state.jsonData .关于您的问题,您需要查看props.jsonData ,而不是state.jsonData This is because the state set operation is async, and the state has not yet been updated when the method is called.这是因为 state 设置操作是异步的,调用该方法时 state 尚未更新。

You don't need both those methods, you can compute your state in the constructor.你不需要这两种方法,你可以在构造函数中计算你的 state 。 Destructure the JSONObj from props, and create the state with the calculations you're already doing in getDerivedStateFromProps - with a small change.从 props 中解构 JSONObj,并使用您已经在 getDerivedStateFromProps 中进行的计算创建getDerivedStateFromProps - 稍作更改。 You need to look at the values of the JSONObj from props , not state .您需要查看来自propsJSONObj的值,而不是state

class NCMenuItems extends Component {
  constructor(props) {
    super(props);
    const {JSONObj} = props;
    this.state = {
     jsonData: JSONObj,
     showPin: JSONObj.showPin === '1',
     direction: JSONObj.direction === '1',
     isCollapsible: JSONObj.isCollapsible === '1',
     cssFilePath: JSONObj.cssFilePath,
     groups: JSONObj.groups

...etc
  }
}

Compute all the data based on the props that you receive, then set those values in state.根据收到的道具计算所有数据,然后在 state 中设置这些值。

You also don't need the ? true: false你也不需要? true: false ? true: false , because the condition is implicitly true or false. ? true: false ,因为条件隐含地为真或假。

This:这个:

showpin: this.state.jsonData.showpin === '1'? true:false,

is equal to:等于:

showpin: this.state.jsonData.showpin === '1'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM