add9
add9

Reputation: 1503

How to pass onChange to a stateless component

I have been playing around with reactjs, and building some basic forms all works good but then it became complicated when i tried to break into smaller compoments i have a simple component that has a form in it called XMLParser, and it has 2 smaller components inside called XMLInput and XMLResult.

XMLResult is pretty straight forward it just passes the value to as the props, but couldnt figure out what is the best approact to use XMLInput i couldnt get the binding to work with the child component, thanks for any pointers.

function EppResult(props) {
    const resultXML = props.xmlData;
 return <div style={styles.child}>
        <textarea style={styles.outputBox} name="resultXML" value={resultXML} readOnly/>
    </div>;

}

class EppInput extends Component{

  render(){
  return <textarea
    style={styles.inputBox}
    placeholder="Enter XML here!"
    name="xmlData"
    value={this.props.value}
    onChange={this.props.handleInputChange}
  />;
}
}


    class XMLParser extends Component {
        constructor(props) {
            super(props);

        this.state = {xmlData : ""};
        this.state = {resultXML : ""};
            this.handleInputChange = this.handleInputChange.bind(this);
            this.handleSubmit = this.handleSubmit.bind(this);
        }

handleSubmit(event) {
    console.log("do submit");
}

        handleInputChange(event) {
            const target = event.target;
            const value = target.type === "checkbox" ? target.checked : target.value;
            const name = target.name;
            this.setState({
                [name]: value
            });
        }

render() {
        return (
            <div style={styles.container}>
                <form onSubmit={this.handleSubmit}>
                    <div style={styles.container}>
                        <div style={styles.child}>
                        <XMLInput value={this.state.xmlData} onChange={this.handleInputChange} />
                        </div>
                        <div style={styles.child}>
                            <div style={styles.formContainer}>

                                <button style={styles.formElement}>Run!</button>
                            </div>
                        </div>
            <XMLResult xmlData={this.state.resultXML}/>
                    </div>
                </form>
            </div>
        );
    }
}

Upvotes: 0

Views: 1580

Answers (1)

Ted
Ted

Reputation: 14927

I'm seeing a number of problems:

  • EppInput is the sub-component name, but XMLInput is used in the main component
  • You pass an onChange prop, but refer to it as this.props.handleInputChange -- it should be this.props.onChange
  • Just a note--I don't know where the styles object is, but I'm going to assume it's available to all the components

I haven't tested this, but here's a basic cleanup, with some alterations to see some other ways of doing things:

// stateless functional component 
const XMLResult = ({ xmlData }) => (
  <div style={styles.child}>
    <textarea
      style={styles.outputBox}
      name="resultXML"
      value={xmlData}
      readOnly
    />
  </div>
);

// stateless functional component
// props are passed directly to the child element using the spread operator 
const XMLInput = (props) => (
  <textarea
    {...props}
    style={styles.inputBox}
    placeholder="Enter XML here!"
    name="xmlData"
  />
);

class XMLParser extends Component {
  constructor(props) {
    super(props);
    this.state = { xmlData: "", resultXML: "" };
    this.handleInputChange = this.handleInputChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleSubmit(event) {
    console.log("do submit");
  }

  handleInputChange(event) {
    const target = event.target;
    const value = target.type === "checkbox" ? target.checked : target.value;
    const name = target.name;
    this.setState({
      [name]: value
    });
  }

  render() {
    return (
      <div style={styles.container}>
        <form onSubmit={this.handleSubmit}>
          <div style={styles.container}>
            <div style={styles.child}>
              <XMLInput
                value={this.state.xmlData}
                onChange={this.handleInputChange}
              />
            </div>
            <div style={styles.child}>
              <div style={styles.formContainer}>
                <button style={styles.formElement}>Run!</button>
              </div>
            </div>
            <XMLResult xmlData={this.state.resultXML} />
          </div>
        </form>
      </div>
    );
  }
}

Upvotes: 1

Related Questions