get promise value in react component

2019-04-06 16:51发布

问题:

I have a helper function in my component. When I console.log(helperFunction()) it, I get this in the console.

When I try to add the helper function to an input field for its value. I get this showing up.

How do I get the [[PromiseValue]] in my input?

  render() {
    console.log(getProjectName());
    return (
      <form ref={(input) => this.eventForm = input} onSubmit={(e) => this.createEvent(e)} className="slds-form">
        <div className="slds-form-element">
          <label className="slds-form-element__label">Assigned To</label>
          <div className="slds-form-element__control">
            <input ref={(input) => this.assigned = input} type="text" className="slds-input"  disabled/>
          </div>
        </div>
        <div className="slds-form-element">
          <label className="slds-form-element__label">Related To</label>
          <div className="slds-form-element__control">
            <input ref={(input) => this.related = input} type="text" className="slds-input" defaultValue={getProjectName()} disabled/>
          </div>
        </div>
        <div className="slds-form-element">
          <label className="slds-form-element__label">Subject</label>
          <div className="slds-form-element__control">
            <input ref={(input) => this.subject = input} type="text" className="slds-input"/>
          </div>
        </div>
        <div className="slds-form-element">
          <label className="slds-form-element__label">Location</label>
          <div className="slds-form-element__control">
            <input ref={(input) => this.location = input} type="text" className="slds-input" />
          </div>
        </div>
        <div className="slds-form-element">
          <label className="slds-form-element__label">Event Start</label>
          <div className="slds-form-element__control">
            <input ref={(input) => this.start = input} type="text" onChange={(e) => this.onChange(e)} className="slds-input" value={ this.state.start }/>
          </div>
        </div>
        <div className="slds-form-element">
          <label className="slds-form-element__label">Event End</label>
          <div className="slds-form-element__control">
            <input ref={(input) => this.end = input} type="text" onChange={(e) => this.onChange(e)} className="slds-input" value={ this.state.end } />
          </div>
        </div>
        <div className="slds-form-element">
          <label className="slds-form-element__label">Contact</label>
          <div className="slds-form-element__control">
            <input ref={(input) => this.contact = input} type="text" className="slds-input" disabled/>
          </div>
        </div>
        <button type="button" className="slds-button slds-button--neutral">Cancel</button>
        <button type="submit" className="slds-button slds-button--brand">Create</button>
      </form>
    );
  }

Helper Function

import axios from 'axios'

export function getProjectName() {

  return new Promise(function(resolve,reject){

  // gets the record id from the current url
  function getQueryVariable(variable) {
    var query = window.location.search.substring(1);
    var vars = query.split("&");

    for (var i=0;i<vars.length;i++) {
      var pair = vars[i].split("=");
      if(pair[0] == variable){return pair[1];}
    }

    return(false);
  }

  // used to access the rest api on my system
  const REST_API_URL = restApiUrl;
  const API_TOKEN = {
    headers: { "Authorization" : "Bearer " + sessionId,
              "Content-Type" : "application/json"
             }
  }
  const OPPORTUNITY_QUERY = "SELECT+Id,Name+FROM+OPPORTUNITY+WHERE+Id="

  // get projectId
  const id = getQueryVariable('projectId');

  // make requst for record name
  var request = axios.get(`${REST_API_URL}query/?q=${OPPORTUNITY_QUERY}'${id}'`,
     API_TOKEN
   ).then(function (response){
      return resolve(response.data.records[0].Name);
   })
  })
}

回答1:

When dealing with a value that the render method will be using and is also retrieved asynchronously you should be having that value exist in the state of the component and take advantage of the componentDidMount lifecycle method to retrieve the value.

class SomeComponent extends React.component {
  constructor() {
    super();

    this.state = {
      projectName: ''
    }
  }

  componentDidMount() {
    // fetch the project name, once it retrieves resolve the promsie and update the state. 
    this.getProjectName().then(result => this.setState({
      projectName: result
    }))
  }

  getProjectName() {
    // replace with whatever your api logic is.
    return api.call.something()
  }


  render() {

    return (
      <input type="text" defaultValue={projectName}>
    )
  }
 }

you don't want to call the function and resolve the promise in the render method because render method should be a pure function based on state and props. This is a base example but should give you an idea of what needs to change. Just need to set projectName as a state variable and make and resolve the promise in the componentDidMount on the first render it will equal an empty string, once it comes back it will update to whatever the api returns.

If you don't want to show the input until the api call resolves then you can just add additional checks to see if this.state.projectName equals anything and if so render the input.



回答2:

The problem with your code is this part.

<input ref={(input) => this.related = input} type="text" className="slds-input" defaultValue={getProjectName()} disabled/>.

The function getProjectName returns a promise, not the resolved value of that promise.

You should render your UI with render() from this.state and this.props, and if you have data that has to be loaded asynchronously, you can assign the data to i.e. this.props.relatedTo using the componentDidMount() function, something in the line of

componentDidMount() {
    var self = this;

    getProjectName()
        .then(val => {
            self.setState({relatedTo: val});
        });
}

Take a look at the state and lifecycle documentation.