0

I'm using React-Native with Redux, where I want to render a button if the logged in user is eligible. Somehow the button is not showing!

For storing data I'm using react-native-simple-store

renderIfEligible(toRender) {
  const building = this.props.building;
  const timings = this.props.timings;

  if (building && timings) {
    store.get(storage.userKey).then(user => {
      if (user != null) {
        if (building.submitter.includes(this.props.userId)) {
          console.log('RENDER');  // THIS IS PRINTED OUT IN THE BROWSER
          return toRender;
        }
      } else {
        console.log('NO RENDER');
        return false;
      }
    });
  }
}

// Function call
{this.renderIfEligible(
   <Button style={{marginTop: 20}} small danger transparent onPress={() => alert("delete")}><Icon name="trash" /></Button>)}

Any idea why the button is not showing up although the console.log() is working?

Update 1

I've added

constructor(props) {
  super(props);
  this.state = { showButton: false};
}
  ....
renderIfEligible(toRender){
  self = this;
  if (building.submitter.includes(this.props.userId)) {
    self.setState({ showButton: true});
  } else {
    self.setState({ showButton: false});
  }
jasonmerino
  • 3,220
  • 1
  • 21
  • 38
imalik8088
  • 1,501
  • 5
  • 21
  • 39

2 Answers2

1

In order to get this button to render correctly based on the react-native-simple-store you will need to initialize the value you expect to get from store.get(storage.userKey) in your component for an initial render and then in componentDidMount call the store.get() method to get the userKey and set that into that same value that you defaulted. Here's a small example.

class MyComponent extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      isEligible: false,
    };
  }

  componentDidMount() {
    store.get(storage.userKey).then(user => {
      if (user !== null) { // add to this if statement any other checks you need
        this.setState({ isEligible: true });
      }
    });
  }

  render() {
    const { building, timings } = this.props;
    const { isEligible } = this.state;

    if (building && timings && isEligible) {
      return (
        <Button ... />
      );
    }
    return null;
  }

}

Basically you just need to give the component a default state until you have the correct data. For this example the default state is that the component returns nothing. I believe, as a general rule, React renders need to be synchronous and so if you need to fetch data asynchronously in order to render correctly you just need to send the component back through the render lifecycle again when the value from the asynchronous query resolves.

jasonmerino
  • 3,220
  • 1
  • 21
  • 38
0

The Button is not showing up because store.get(storage.userKey) is returning a promise of a user object which is then being mapped into a component (or false) using the then function.

As you aren't returning the result of the then function, the result of renderIfEligible is always undefined (your returns are for the lambda function).

Unfortunately for you, just changing the function to return store.get(storage.userKey).then(user => {...}) wont help you as then it will be returning a promise of a component (or false), which is still unable to be rendered.

Take a look at this answer for ideas on how to get around this.

Community
  • 1
  • 1
Michael Peyper
  • 6,814
  • 2
  • 27
  • 44
  • I've tried this approach (kind of) before putting this to Stackoverflow, without saving the `this` to a const. But it didn't help :-( – imalik8088 Apr 28 '17 at 09:11