Solid project for simplifying the your react interactions with a server API data models

react-refetch

import React from "react";  
import ReactDom from "react-dom";  
import { connect, PromiseState } from "react-refetch";  
import { globalStyles } from "../../styles";  
import { Urls } from "../../redux/serviceurls";  
import * as Notify from "../utilities/notify";

class ConnectionConfig extends React.Component {

  constructor(props) {
    super(props);
    this.title = "Connection Config";
    this.onUrlChanged = this.onUrlChanged.bind(this);
    this.onVendorIdChanged = this.onVendorIdChanged.bind(this);
    this.onVersionChanged = this.onVersionChanged.bind(this);
    this.resetFields = this.resetFields.bind(this);

    this.state = {
        url: "",
        vendorId: "",
        version: ""
    };
  }

  onUrlChanged(e) {
    this.setState({ url: e.currentTarget.value });
  }

  onVendorIdChanged(e) {
    this.setState({ vendorId: e.currentTarget.value });
  }

  onVersionChanged(e) {
    this.setState({ version: e.currentTarget.value });
  }

  componentWillReceiveProps(nextProps) {
    const promiseState = nextProps;

    if (promiseState.config.fulfilled) {
      this.setState({
        url: promiseState.config.value.url,
        vendorId: promiseState.config.value.vendorId,
        version: promiseState.config.value.version
      });
    }
  }

  displayFuncs() {
    return {
      success: () => Notify.info({ title: this.title, message: "Saved" }),
      error: (reason, meta) => {
        console.log(reason);
        Notify.warning({ title: this.title, message: "You have entered invalid inputs" });
      }
    };
  }

  resetFields() {
    let values = this.props.config.value;
    if (this.props.config.rejected) {
      values = this.props.lastValid.value;
    }
    this.setState({
      url: values.url,
      vendorId: values.vendorId,
      version: values.version
    });
  }

  renderRow(options) {
    return (
      <div style={styles.divStyles.rowWidth}>
        <div style={styles.leftColumn}>
          <span style={styles.text}>{options.text}</span>
        </div>
        <div style={styles.right}>
          <input type="text" value={options.value} onChange={options.onChange} style={styles.inputStyle} />
        </div>
      </div>
    );
  }

  render() {
    const that = this;
    return (
      <div>
        <div style={styles.divStyles.headerRow}>
          <span style={styles.header}>Connection</span>
        </div>
        { this.renderRow ({
          text: "URL:",
          onChange: this.onUrlChanged,
          value: this.state.url
        })}
        {this.renderRow({
          text: "Vendor ID:",
          onChange: this.onVendorIdChanged,
          value: this.state.vendorId
        })}
        {this.renderRow({
          text: "Version:",
          onChange: this.onVersionChanged,
          value: this.state.version
        })}
        <div style={styles.divStyles.rowWidth}>
          <div style={styles.leftColumn}>
          </div>
          <div>
            <input type="button" style={styles.buttonStyle} value="Save" onClick={
              function () {
                that.props.postConfig(
                  that.state.url,
                  that.state.vendorId,
                  that.state.version,
                  that.displayFuncs());
              }} />
            <input type="button" style={styles.buttonStyle} value="Undo" onClick={this.resetFields} />
          </div>
        </div>
      </div>
    );
  }
};

export default connect(props => ({  
  lastValid: { url: Urls.Config.Connection },
  config: { url: Urls.Config.Connection },
  postConfig: (url, vendorId, version, fns) => ({
    config: {
      url: Urls.Config.Connection,
      method: "POST",
      body: JSON.stringify({ Name: "Connection", Url: url, VendorId: vendorId, Version: version }),
      then: fns.success,
      catch: fns.error
    }
  })
}))(ConnectionConfig);