user3802348
user3802348

Reputation: 2592

Handling promises among multiple React components

I am having trouble manipulating a series of promises in an application I’m building.

My main component renders a React component Button, like so:

ButtonsList.js

<Button
    onClick={() => {
        this.props.onButtonClicked().then(() => {
            console.log(‘got in then’)
        }).catch(() => {
            console.log(‘got in catch’)
        )}
    }
>

When the button is clicked, it calls a function in the parent component, onButtonClicked.

PageItems.js

onButtonClicked = () => {
    return this.onSubmit().then((promiseValue) => {
        console.log(promiseValue)
    }).catch((error) => {
        console.log(error);
        console.log(‘promise rejected’);
    });
   }

The parent onSubmit calls a function that returns a promise.

onSubmit = () => {
    errors = this.checkForErrors();
    if (errors) {
        return Promise.reject(‘has errors’);
    } else {
        return Promise.resolve(‘no errors’);
    } 
 }

My console log statements for “has errors” and “promise rejected” are logged, but in the console I get an error in ButtonsList.js: Uncaught TypeError: Cannot read property 'then' of undefined. I’ve read this error often comes up when.a promise is not successfully returned, but I can’t figure out what I’m missing. Any help greatly appreciated!

Upvotes: 0

Views: 1374

Answers (2)

devserkan
devserkan

Reputation: 17618

You have a syntax problem in your Button component. Also, you don't return anything in your second onButtonClicked function. So, it always drops the .then method. I return them here.

class App extends React.Component {
  checkForErrors = () => true;

  onSubmit = () => {
    const errors = this.checkForErrors();
    if ( errors ) {
      return Promise.reject( "has errors" );
    }
    return Promise.resolve( "no errors" );
  }

  onButtonClicked = () => this.onSubmit().then( ( promiseValue ) => {
    console.log( promiseValue );
    return Promise.resolve( promiseValue );
  } ).catch( ( error ) => {
    console.log( error );
    console.log( "promise rejected" );
    return Promise.reject( error );
  } )

  render() {
    return <div><ButtonsList onButtonClicked={this.onButtonClicked} /></div>;
  }
}

const ButtonsList = props => (
  <div>
    <button
      onClick={() => {
        props.onButtonClicked()
          .then( () => {
            console.log( "got in then" );
          } )
          .catch( () => {
            console.log( "got in catch" );
          } );
      }}
    >Click
    </button>
  </div>
);

ReactDOM.render(
  <App />,
  document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Upvotes: 1

Ravi Rane
Ravi Rane

Reputation: 159

Your onButtonClick is not returning any promise. You can try below code, I am just hardcoding error case, but you can try same for success.

        class App extends React.Component {
          constructor(props) {
            super(props);
          }

          onSubmit = () => {
            let errors = true;
            if (errors) {
              return Promise.reject("has errors");
            } else {
              return Promise.resolve("no errors");
            }
          }

          onButtonClicked = () => {
            return this.onSubmit().then((promiseValue) => {
              console.log(promiseValue)
            }).catch((error) => {
              console.log(error);
              console.log("promise rejected");
              return Promise.reject("promise rejected - from promis");
            });
          }

          _onClick = () => {
              this.onButtonClicked().then(() => {
                console.log("got in then");
              }).catch((e) => {
                console.log(e);
                console.log("got in catch");
              })
          }

          render() {
            return (
              <button onClick={this._onClick} />
                );
              }
            }

            const rootElement = document.getElementById("root");
        ReactDOM.render(<App />, rootElement);

Code - https://codesandbox.io/s/yjkn761m4z

Upvotes: 0

Related Questions