Jeremy Wagner
Jeremy Wagner

Reputation: 143

Use Native Base Toast To Show Error From Redux Action

I'm using NativeBase in a React Native app. I'm trying to show a Toast component based on an error that is set in an redux action because it happens via a call to the API.

It will show now, but currently I get the warning message:

Warning: Cannot update during an existing state transition (such as within render or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to componentWillMount.

I'm not sure how I could bind this or what I could do to solve the warning.

Render Method

render() {
  return (
    <View>
      {this.renderError()}
      {this.renderForm()}
    </View>
  );
}

Render Error Method

renderError() {
  if (this.props.error.type === 'server') {
    return (
      Toast.show({
        text: this.props.error.message,
        buttonText: 'Okay',
        duration: 5000,
        type: 'danger'
      })
    );
  }
}

Versions

React Native: 0.55.4

Native Base: 2.4.5

Edit: Adding an example for clarity

I need to show a Toast based on the response from the server. For example, if the username and password don't match an account, I need to render the Toast.

Solution:

I ended up creating a ToastService:

import { Toast } from 'native-base';

function showToast(message) {
  return (
    Toast.show({
      text: message,
      buttonText: 'Okay',
      duration: 5000,
      type: 'danger'
    })
  );
}

export default {
  showToast
};

and now in my action I can just call:

ToastService.showToast(data);

Upvotes: 6

Views: 9918

Answers (4)

Howie
Howie

Reputation: 1854

Like Dwayne says above, you need to use useEffect so that Toast is called before the render cycle. You can wrap this is a component like so:

const ErrorToast: React.FC = () => {
    const {state} = useCollections();
    useEffect(() => {
        if(state.errored) {
            Toast.show({
                text: 'Oops. There has been an error',
                duration: 2000
            });
        }
    });

    return null;
}

And then simply include it as <ErrorToast />

Upvotes: 0

Dwayne Love
Dwayne Love

Reputation: 343

I solved this issue by using React Hooks.

() => {
       useEffect(() => {
           if(error) {
               Toast.show({
                   text: this.props.error.message,
                   buttonText: 'Okay',
                   duration: 5000,
                   type: 'danger'
               })
            }
        })

        return (
            <View>
                {this.renderForm()}
            </View>
        );
    }

Upvotes: 3

EQuimper
EQuimper

Reputation: 5929

You can create a function and call this one outside. But make sure your app is wrap with the Root component of native-base. No need to return a component like you do. Calling this function gonna show the toastr and now you have the freedom to call from anywhere. But make sure Root component wrap your app.

import { Toast } from 'native-base';

export const toastr = {
  showToast: (message, duration = 2500) => {
    Toast.show({
      text: message,
      duration,
      position: 'bottom',
      textStyle: { textAlign: 'center' },
      buttonText: 'Okay',
    });
  },
};

Now inside your action you can call the toastr function

toastr.showToast('Verication code send to your phone.');

Or in redux actions

const signup = values => dispatch => {
  try {
    // your logic here


  } catch (error) {
    toastr.showToast(error.message)
  }
}

Upvotes: 5

Supriya Kalghatgi
Supriya Kalghatgi

Reputation: 1155

Check React Native Seed for this implementation https://reactnativeseed.com/

Upvotes: 1

Related Questions