在反应之间提升组件之间的状态

时间:2018-08-16 10:11:32

标签: json reactjs lift

我对React组件之间的通信有疑问。我想将组件“ ProductNameSave.js”之间的值传递给“ readJson.js”。来自“ ProductNameSave.js”的值来自组件“ windowForm.js”。由于这种结构(“ windowForm.js”->“ ProductNameSave.js”->“ readJson.js”),我认为“ ProductNameSave.js”是“来源”。 这里是组件。 “ windowForm.js”

import React from 'react';
import Input from '@material-ui/core/Input';
import UploadPicture from './UploadPicture.js';

export default class FormWindow extends React.Component{
    state ={
        U_Factor:'',
        Solar_Heat_Gain_Coefficient:'',
        Visible_Transmittance:''
    };

    change = e =>{
        this.setState({
            [e.target.name]: e.target.value
        });
    };

    onSubmit= e =>{
        e.preventDefault();
        this.props.onSubmit(this.state);
        this.setState({
            U_Factor:'',
            Solar_Heat_Gain_Coefficient:'',
            Visible_Transmittance:''
        });
    };

    render(){
        return(
            <form className="productForm">
                <Input 
                    name="U_Factor"
                    placeholder="U-Factor" 
                    value={this.state.prodValue1} 
                    onChange={e => this.change(e)}
                />
                <br />
                <Input 
                    name="Solar_Heat_Gain_Coefficient"
                    placeholder="Solar Heat Gain Coefficient"
                    value={this.state.prodValue2} 
                    onChange={e => this.change(e)}
                />
                <br />
                <Input 
                    name="Visible_Transmittance"
                    placeholder="Visible Transmittance" 
                    value={this.state.prodValue3} 
                    onChange={e => this.change(e)}
                />
                <br />
                <UploadPicture/>
               <button onClick={e => this.onSubmit(e)}>Submit</button>
            </form>    
        )
    }
}

“ ProductNameSave.js”:

import React from 'react';
import FormWindow from './windowForm.js';


export default class ProductNameSave extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      field:'', 
      open: false
    };
  }

  state = {
    fields:{}
  };

  handleChance(fields){
    this.setState({fields})
  }

  onSubmit = (fields) => {
    this.setState({fields});
    console.log('App component got: ', fields);
  };

  render() {
    const fields = this.state.fields
    return (
      <div>
        <FormWindow  onSubmit ={fields => this.onSubmit(fields)} />
      </div>
    );
  }
}

“ readJson.js”:

import React from 'react';
import MyAppChild from './readJsonChild.js';
import data from '../../model/data/ProductData/Material.json';
import ProductNameSave from '../ProductList/ProductNameSave.js';

export default class MyApp extends React.Component {

  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = {fields: ''};
  }

  handleChange(fields) {
    this.props.onValueChance({fields});
  }

  render() {
      const fields = this.props.fields;
      var json2 = data[0]      
      var arr = [];
      Object.keys(json2).forEach(function(key) {
        arr.push(json2[key]);
      });
    return 
      <ul>{arr.map(item => <MyAppChild key={item.Name} Name={item.Name} Roughness={item.Roughness} Thickness={item.Thickness} />)}</ul>;
      <ul><ProductNameSave onChance ={fields => this.handleChange(fields)}/></ul>;
  }
}

“ readJson.js”从单独的组件获取其值。目的是通过ProductNameSave将windowForm.js中的值传递给readJson,以使用ProductNameSave中的新值覆盖reaJson中的值。 如果运行代码,则会出现以下错误: 错误:MyApp.render():必须返回有效的React元素(或null)。您可能返回了undefined,数组或其他无效对象。

有人知道我如何解决这个问题吗?

非常感谢您!

3 个答案:

答案 0 :(得分:1)

如果您使用的是React版本> 16,也可以使用<ul class="sidebar-menu"> @{ if (ViewBag.MenuList != null) { foreach (var items in ViewBag.MenuList.Items) { string action = items.ActionName; string controller = items.ControllerName; <li class="treeview"> @if (items.ParentID == items.MenuID) { <ul class="treeview-menu"> <li class="treeview"> <a href="/@items.ControllerName/@items.ActionName"> <i class="fa fa-angle-double-right"></i> <span>@items.MenuText</span> <i class="fa fa-angle-left pull-right"></i> </a> </li> </ul> } <a href="/@items.ControllerName/@items.ActionName"> <i class="fa fa-user"></i> <span>@items.MenuText</span> <i class="fa fa-angle-left pull-right"></i> </a> </li> } } } 。这样可以避免在DOM中添加另一个元素只是为了对其他JSX元素进行分组。

<React.Fragment>

参考:ReacJS Doc for Fragment

ReactJS还提供了另一种快捷方式,而其他工具尚不支持这种方式。可以在上面的文档页面中读取相同的内容。

答案 1 :(得分:0)

问题在readJson.js中。该组件返回JSX的方式不正确。在React 15中,每个组件JSX元素都必须用div或span等封闭。

检查下面的更新代码

import React from 'react';
import MyAppChild from './readJsonChild.js';
import data from '../../model/data/ProductData/Material.json';
import ProductNameSave from '../ProductList/ProductNameSave.js';

export default class MyApp extends React.Component {

  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = {fields: ''};
  }

  handleChange(fields) {
    this.props.onValueChance({fields});
  }

  render(){
    const fields = this.props.fields;
      var json2 = data[0]      
      var arr = [];
      Object.keys(json2).forEach(function(key) {
        arr.push(json2[key]);
      });
    let children = [];
    arr.map((item, i) => {
        children.push(<MyAppChild key={item.Name} Name={item.Name} Roughness={item.Roughness} Thickness={item.Thickness} />);
    });
return(
    <div>
        <ul>
        {children}
        </ul>
        <ul><ProductNameSave onChance ={fields => this.handleChange(fields)}/></ul>
    </div>
    )
}
}

如果您的组件返回单个jsx元素,则无需将它们括在div或span之间,如果多个jsx元素,则必须将其包围。

答案 2 :(得分:0)

不要尝试通过ProductNameSave从windowForm.js提升状态到readJson,这是一个反模式。相反,您可以执行以下操作:

  1. 在父组件中定义状态(在您的情况下,这可能是readJson组件),并定义一个方法,该方法将更改状态并将其传递给子组件(在您的情况下为windowForm.js)。定义了此类方法并将其传递给子组件后,您将能够在子组件内部调用此方法,并且该方法将更改父组件中的状态。

OR

  1. 使用Redux并将数据保持在全局状态。这些数据将在您所有的组件中提供。