0

I'm creating an intake form where a piece of data can be input into the text field, or generated randomly with a button next to the field.

I want to do this for 3 fields on the form so I created a component called <RandomDataButton />

I'm stuck with how to make sure the results of the calculation done by the button component update the value of the text box so that the form submission contains the generated data.

I don't fully understand the state propagation, but what I do understand is that the flow is one way, down the hierarchy of components.

So what I am attempting to do is have a choice of inputting some data in the text box, or generating some random data from a button (I'd like to reuse it in other ui creations)

Where I am stuck is how do I update the input field from the componenet that is lower in the hierarchy.

Do I pass the state to the randomizer button and then have it update a copy of state? Or am I totally off base with that approach?

App:

class App extends React.Component {

  render(){
    return (
      <div>
      <DataInputForm />
      </div>
    );
  }
}

DataInputForm:

class DataInputForm extends React.Component{

    state= {
        projectname: '',
        datasource: '',
        data1: '',
        data2: '',
        data3: '',
    };

    handleSubmit = e => {
        e.preventDefault();
        console.log({
            projectname: this.projectname.value,
            datasource: this.datasource.value,
            data1: this.data1.value,
            data2: this.data2.value,
            data3: this.data3.value,
        });
    }

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

    render(){
        return(
            <form className="ui form" onSubmit={this.handleSubmit}>
                <div className="field">
                    <label htmlFor="projectname">Project Name: </label>
                    <input 
                        type="text" 
                        id="projectname"
                        name="projectname"
                        placeholder="Project Name"
                        ref={input => this.projectname = input}
                    />
                </div>
                <div className="field"> 
                    <label htmlFor="datasource">Data Source: </label>
                    <input 
                        type="text" 
                        id="datrasource" 
                        name="datasource" 
                        placeholder="Data Source" 
                        ref={input => this.datasource = input}
                    />
                </div>
                <div className="field">
                    <label htmlFor="data1">Data 1: </label>
                    <input 
                        type="number" 
                        min="3"
                        max="18"
                        id="data1"
                        name="data1"
                        ref={input => this.data1 = input}
                    />                  
                    <RandomDataButton buttonid={"data1button"} buttonname={"Data1"} />
                </div>
                <div className="field">
                    <label htmlFor="data2">Data 2: </label>
                    <input 
                        type="number" 
                        min="3"
                        max="18"
                        id="data2"
                        name="data2"
                        ref={input => this.data2 = input}
                    />                  
                    <RandomDataButton buttonid={"data2button"} buttonname={"Data2"} />
                </div>
                <div className="field">
                    <label htmlFor="data3">Data 3: </label>
                    <input 
                        type="number" 
                        min="3"
                        max="18"
                        id="data3"
                        name="data3"
                        ref={input => this.data3 = input}
                    />                  
                    <RandomDataButton buttonid={"data3button"} buttonname={"Data3"} />
                </div>
                    <button className="ui button" type="submit">Create Data</button>
            </form>
        );
    }
}

RandomDataButton:

const getRandom = max => Math.floor(Math.random() * Math.floor(max));

class RandomDataButton extends React.Component {

    generateData(value){
        var result, destination;
        destination = value.toLowerCase();

        result = getRandom(1000);
        console.log("Generated " + result + " for range of " + value + "]: " + destination);
        //this.state.{destination};
    }

    render(){
        return(
            <button id={this.props.buttonid} type="button" onClick={this.generateData.bind(null,this.props.buttonname)}>{this.props.buttonname}</button>
            //<button id="strbutton" type="button">Generate</button>
        );
    }
}
1
  • Put the update method in the DataInputForm , then use props pass in RandomDataButton Commented Jun 12, 2019 at 5:22

3 Answers 3

2

Pass a function as prop to RandomDataButton. Define the function in DataInputForm and use it update the state in DataInputForm by calling the prop function from RandomDataButton whenever you need the update.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. I had to research how to do that, but it gave the answer I needed.
1

It seems you are working with multiple components, so while working with multiple components, it is highly recommended to use any central storage container, which would be useful to get your desired data in any components

Flux and redux both are tested architectures for data state management, you could use any of them, I would recommend using redux.

2 Comments

That seems useful further down the line. I really would like to keep this simple and understand the concept rather than get into the complexities of yet more frameworks and architectures. I want to know how to handle this simple concept with what I have, not add more things.
for simplicity, Amala James has posted a comment. you just need to define a function in parent component and pass it to child component as a prop , the only thing you would require is just to call the function from the child component with desired data as a parameter.
1

Here's a codesandbox for your reference: https://codesandbox.io/s/bold-frog-01ff2

This is effectively a continuation of Amala's suggestion.

You are correct, the hierarchy is one-way. Which means we should define a function in DataInputForm (lvl2) and pass it as a prop to RandomDataButton (lvl3). That function is bound to DataInputForm's execution context, and we want to update it's state so we can feed the new data back into each individual input.

For example:

  createRandomText = (associatedField, value) => {
    this.setState(
      {
        [associatedField]: value
      },
      () => console.log(this.state)
    );
  };

So to update the state correctly, we need to provide a field corresponding to the right input, and a value (the randomized value).

We pass in that function as a prop to RandomDataButton and use it for the onClick() handler.

class RandomDataButton extends React.Component {
  generateData = () => {
    let result = getRandom(1000);

    this.props.createRandomText(this.props.matchingInput, result);
  };

  render() {
    return (
      <button
        id={this.props.buttonid}
        type="button"
        onClick={this.generateData}
      >
        {this.props.buttonname}
      </button>
      //<button id="strbutton" type="button">Generate</button>
    );
  }
}

Additionally we need to provide another prop to the button component so we can call the above function correctly:

  <RandomDataButton
    buttonid={"data1button"}
    buttonname={"Data1"}
    createRandomText={this.createRandomText}
    matchingInput={"data1"}
  />

See sandbox for full details :)

2 Comments

Yes. Thank you. I had to research a bit how to do that, and your answer confirms that my research concluded properly.
@KenIngram You're welcome. Remember to hook-up your onChange handler and state-values, looks like you were saving that for the end :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.