Search code examples
javascripthtmlonchangecreate-react-app

Making inputs that update props onChange when using create-react-app structure?


I am making a web based calculator tool which will update the graph in real time as the four input fields are altered by the user.

The problem is, I do not understand props well enough to do it. And I am getting all kinds of errors for something that should only be 3 lines of code (maybe more if i cannot update all the this.income. simultaneously.

It is also further complicated by the props->render->return structure of Create-react-app since basically there is a js area and an html area.

Note: Some of the code below may be redundant such as the const props, since I am using this. instead.

This is what it looks like:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import { Collapse,  Navbar, Form,  NavbarToggler,    NavbarBrand,    Nav,    
NavItem,    NavLink,    Container,    Row,  Col,  Jumbotron,  Button,  
ButtonToolbar    } from 'reactstrap';
import { zingchart }from 'zingchart';
import {core as Core} from 'zingchart-react';

class App extends React.Component {
  constructor(props) {
        super(props);

      //  this.handleChange = this.handleChange.bind(this);

  //These may not be needed:
        const trd = 0;
        const itr = 7;
        const lit = 6;
        const tei = 4;


        //this array of props keep track of values:
        this.income = {trd:8,itr:8,lit:8,tei:8};
        //this array sends values to the graph:
        this.formula = { a: ((this.income.lit*this.income.trd)*(1- 
        this.income.itr)), b: (this.income.lit*this.trd), c: this.income.tei}

        //Logic for Graph:
        //a = (lit * trd) * 1 - itr
        //b = lit * trd
        //c = tei
  }

        // function updateAField(modifiable,goalValue){
        //   modifiable = goalValue;
        // };


  render() {
    var myConfig = {
    // This is just the irrelevant graph info - it has been shortened for 
    // readability on stackOverflow
               type: "bar3d",
               "stacked": true,
               series : [{values : [this.formula.a, this.formula.b, 
               this.formula.c]}]
             };

    return (

      <div class="row">
        <div class="column">
          <div className="App">
                  <header className="App-header">

                          <header className="App-form">
                          <br/><br/><br/><br/><br/><br/>
                                    <form>
                                    <label class="title" >Income 
 Distribution</label>
                                    <br/>
                                    <br/>
                                    <br/><label>Traditional/Roth Dist% 
 </label>
              <input id="trd" type="text" value={this.income.trd} onChange= 
              {this.income.trd.bind(this) } required />
                                    <br/><label>Income Tax Rate %</label>
              <input id="itr" type="text" value={this.income.itr} onChange={e 
              => this.onChange(e.target.value)} required />
                                    <br/><label>Life Insurance Total 
 $</label>
              <input id="lit" type="text" value={this.income.lit} onChange={e 
              => this.onChange(e.target.value)} required/>
                                    <br/><label>Tax Exempt Income $</label>
              <input id="tei" type="text" value={this.income.tei} onChange={e 
               => this.onChange(e.target.value)} required/>
                                    </form>
                                  <br/>
                            </header>
                    </header>
                </div>
              </div>
                  <div class="column">
                  <img src="./bws.jpg" className="App-logo" alt="logo" />
                  <p>Define Your Future</p>
                  <Core id="myChart" height="400" width="800" data={myConfig} 
  />
                  <a className="App-link"href=""target="_blank"rel="noopener 
  noreferrer">Return to BWS</a>
                  </div>
      </div>
    );
  }
 }

export default App;

Solution

  • I think what you are missing is the idea of state in React. Components will only re-render when one of three things happen:

    1. Props change (abstracted into shouldComponentUpdate)
    2. State changes (abstracted into shouldComponentUpdate)
    3. A call to this.forceUpdate

    Anything that you expect to be changed in the component that should impact what is rendered when it changes needs to be stored in state. Right now after your initial render your component will never update again since you never change state and you never change the props being passed in by the parent.

    import { PureComponent } from 'react';
    
    class MyComponent extends PureComponent {
      static propTypes = {
        initialValue: PropTypes.number,
      }
    
      constructor(props) {
        super(props);
    
        this.state = {
          valueThatChanges: props.initialValue;
        };
      }
    
      handleChange = (event) => {
        this.setState({ valueThatChanges: calculateValue(event) });
      }
    
      render() {
        return (
          <input onChange={this.handleChange} value={this.state.valueThatChanges} />
        );
      }
    }