1

I am learning React Native and this is my first post at Stack Overflow.

I'm trying to re-render a button to make its disabled property change from false to true when onPress.

This button is being manually rendered insiderenderMessageImage from react-native-gifted-chat.

I am doing it through a boolean in this.state, however I see the state value updating on the logs but the button remains visually the same and it can be pressed again and again without actually changing its disabled property.

I have in my Chat.js class:

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

Then from Gifted Chat I call renderMessageImage to show a custom message design when a message has an image:

renderMessageImage = (props) => {
      return (
      <View>
          <Button
            title="Disable Button"
            disabled={this.state.isButtonDisabled}
            onPress={() => this.disableButton(props.currentMessage.id)}
          />
      </View>)
}

This custom design is just a button that should call another method and then disable self:

disableButton = async (message_id) => {
      console.log("Disabling message_id: " + message_id); //This shows the msg_id correctly where the button is
      console.log(this.state.isButtonDisabled); //This shows false
      this.setState(previousState => ({
          isButtonDisabled: true
        }));
      console.log(this.state.isButtonDisabled); //This shows true (should update button disabled property)
      return true;
}

For what I have tested so far, I can see that state value of isButtonDisabled is correctly changing from false to true, and as I have read, a change in the state should make the component re-render, but unfortunately it is not working that way.

More in-depth testing:

I then headed to GiftedChat.js sources from the react-native-gifted-chat to try debugging some of the code and see what is going on there. What I found is that whenever I press my custom button, the componentDidUpdate of GiftedChat.js is being called twice:

componentDidUpdate(prevProps = {}) {
    const { messages, text, inverted } = this.props;
    console.log(this.props !== prevProps); //This is called twice per button click
    if (this.props !== prevProps) {
        //this.setMessages(messages || []); //I changed this line for the line below to directly update state
        this.setState({ messages });
        console.log(this.props !== prevProps); //This is called once per button click (first of the two calls)
    }
    if (inverted === false &&
        messages &&
        prevProps.messages &&
        messages.length !== prevProps.messages.length) {
        setTimeout(() => this.scrollToBottom(false), 200);
    }
    if (text !== prevProps.text) {
        this.setTextFromProp(text);
    }
}

Once all this checked, I see that the state is being updated and the GiftedChat.js component and messages are being updated once per button click, however my button in renderMessageImage is never re-rendering to properly show its new disabled value and actually become disabled.

I am totally clueless what else to test, so I would really appreciate some help on what am I doing wrong.

Thank you very much in advance.

Edit: renderMessageImage is called by GiftedChat on my Chat.js class render() section, then GiftedChat will call this.renderMessageImage whenever a message has an image (eg. this.state.messages[i].image != undefined). That part is working correctly, everything is being called as it should, just the re-render of the button status (disabled) is not updating:

  render() {
    return (
      <View style={{ flex: 1 }}>
        <GiftedChat
          messages={this.state.messages}
          onSend={this.sendMessage}
          user={this.user}
          placeholder={"Write a message..."}
          renderMessageImage={this.renderMessageImage}
        />
        <KeyboardAvoidingView behavior={'padding'} keyboardVerticalOffset={80}/>
      </View>
    );
  }
vildor
  • 11
  • 1
  • 4
  • Where do you call `renderMessageImage`? Please provide the code. Also your second log of `console.log(this.state.isButtonDisabled);` should actually not show `true` but still `false` because state updates are async. Do you mutate `this.state.isButtonDisabled` manually somewhere else? – trixn Mar 03 '20 at 15:39
  • Hi @trixn thanks for commenting. `renderMessageImage` is called by GiftedChat, I set it inside the `render()` section of my `Chat.js` class, I have edited the question and added the code. You are right about the `console.log(this.state.isButtonDisabled);`, but I can check it elsewhere later and the state value is actually changing, so sooner or later that should be forcing the component to re-render (?).. That is the part which I don't understand so far. Also `this.state.isButtonDisabled` is only being modified inside `disableButton`, I'm not setting or reading it in any other places. – vildor Mar 03 '20 at 20:44

0 Answers0