简体   繁体   中英

React Sibling Components Communicate When Button Pressed (Login Form)

I am looking to have communication between sibling components. The thought is for the Username and Password fields to be separate React components and another button component would request the values from those components and run the login check. What I have so far (not working with any sort of communication but not for lack of searching) is below.

import React from 'react';
var LoginDataModel = require ('./loginDataModel');

var LoginPage = React.createClass({
  getInitialState: function() { console.log(LoginDataModel); return LoginDataModel },
  render: function() {
    console.log(LoginDataModel.getUsername);
    return (
      <div className="container view-header">
        <LoginForm/>
      </div>
    );
  }
});

var LoginForm = React.createClass({
  render: function() {
    return (
      <form className="form-signin" name="loginForms">
        <UsernameInput/>
        <PasswordInput/>
        <SubmitButton/>
      </form>
    );
  }
})

var UsernameInput = React.createClass({
  getInitialState: function() {
    return {userValue: ''};
  },
  handleChange: function(event) {
    this.setState({userValue: event.target.value});
  },
  render: function() {
    return (
      <div className="form-group">
        <label htmlFor="inputEmail">Username</label>
        <input autofocus className="form-control" id="inputEmail" placeholder="Username" name="loginUsername" required type="text" ref="usernameInput" value={this.state.userValue} onChange={this.handleChange}></input>
      </div>
    );
  }
});

var PasswordInput = React.createClass({
  getInitialState: function() {
    return {passValue: ''};
  },
  handleChange: function(event) {
    this.setState({passValue: event.target.value});
  },
  render: function() {
    return (
      <div className="form-group">
        <label htmlFor="inputPassword">Password</label>
        <input autofocus className="form-control" id="inputPassword" placeholder="Password" name="loginPassword" required type="text" ref="passwordInput" value={this.state.passValue} onChange={this.handleChange}></input>
      </div>
    );
  }
});

var SubmitButton = React.createClass({
  contextTypes: {
      userValue: React.PropTypes.any,
      passValue: React.PropTypes.any
    },
    render: function () {
      return (
        <div>
          Active Item: {this.context.userValue}
        </div>
      );
    }
})

export default() => <LoginPage/>;

Any help would be much appreciate!

Edit 1:

Ignore the LoginDataModel as it is unused as I was going for a singleton but decided against it unless someone can tell me I should do that...

A very simple implementation (I am a beginner in React) would be to let the wrapper component handle the logic and state; ie let the LoginForm become:

var LoginForm = React.createClass({
    getInitialState: function() {
        return {
            username: null,
            password: null
        }
    },
    setUsername: function(username) {
        this.setState({username: username});
    },
    setPassword: function(password) {
        this.setState({password: password});
    },
    doLogin: function() {
        // execute the login logic, based on this.state.username/password
    },
    render: function() {
        return (
            <form className="form-signin" name="loginForms">
                <UsernameInput onChange={this.setUsername} />
                <PasswordInput onChange={this.setPassword} />
                <SubmitButton onClick={this.doLogin} userValue={this.state.username} />
            </form>
        );
    }
})

And the subordinate components communicate with the wrapper through callbacks, ie the onChange event for inputs:

var UsernameInput = React.createClass({
    handleChange: function(event) {
        this.props.onChange && this.props.onChange(event.target.value);
    },
    render: function() {
        return (
            <div className="form-group">
                <label htmlFor="inputEmail">Username</label>
                <input autofocus className="form-control" id="inputEmail" placeholder="Username" name="loginUsername" required type="text" onChange={this.handleChange}></input>
            </div>
        );
    }
});

var PasswordInput = React.createClass({
    handleChange: function(event) {
        this.props.onChange && this.props.onChange(event.target.value);
    },
    render: function() {
        return (
            <div className="form-group">
                <label htmlFor="inputPassword">Password</label>
                <input autofocus className="form-control" id="inputPassword" placeholder="Password" name="loginPassword" required type="text" onChange={this.handleChange}></input>
            </div>
        );
    }
});

And the onClick event for the button:

var SubmitButton = React.createClass({
    onClick: function() {
        this.props.onClick && this.props.onClick();
    },
    render: function () {
        return (
            <div>
                Active Item: {this.context.userValue}
                <button onClick={this.onClick}>Submit</button>
            </div>
        );
    }
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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