Ati
Ati

Reputation: 304

React useState hook with callback

I'm having a hard time converting the following methods with setState

sendMsgToMe = () => {
    const { senderIdString, senderId } = this.props; //eslint-disable-line
    const { messages, counter } = this.state;
    let myNumber;
    this.setState({
      btnSendMeIsDisabled: true,
    });
    axios
      .get(`${appConfig.URL_REST}user`, {
        headers: { Authorization: `Bearer ${localStorage.getItem('token')}` },
      })
      .then((response) => {
        myNumber = response.data.phoneNumber;
        this.setState(
          {
            messageToSend: [
              {
                from: senderIdString ? senderIdString.number : senderId,
                to: myNumber,
                message: messages[counter],
              },
            ],
          },
          this.sendMsgAxios
        );
      });
  };

  sendMsgToRecipients = () => {
    const { recipientsNmbs, senderIdString, senderId } = this.props;
    const { messages, counter } = this.state;
    this.setState({
      btnSendIsDisabled: true,
    });
    const msgToSend = recipientsNmbs.map((item) => {
      return {
        from: senderIdString ? senderIdString.number : senderId,
        to: item,
        message: messages[counter],
      };
    });
    this.setState(
      {
        messageToSend: msgToSend,
      },
      this.sendMsgAxios
    );
  };

into functions. I saw examples with calling it from useEffect with dependency array but they were more plain. The main issue in this piece of code

this.setState(
          {
            messageToSend: [
              {
                from: senderIdString ? senderIdString.number : senderId,
                to: myNumber,
                message: messages[counter],
              },
            ],
          },
          this.sendMsgAxios
        );

My questions is how exactly should I call it in useEffect or is there any better approach?

Upvotes: 1

Views: 113

Answers (2)

Fraction
Fraction

Reputation: 12954

You could use a new state callSendMsgAxios that will trigger sendMsgAxios when sendMsgToMe or sendMsgToRecipients are executed, your component will look like:

...
// useReducer is better in this case
const [state, setState] = useState({
  messages: '',
  counter: '',
  btnSendMeIsDisabled: false,
  messageToSend: [{
    from: '',
    to: '',
    message: ''
  }],
  callSendMsgAxios: false,
  ...
});


useEffect(() => {
  if(callSendMsgAxios) {
    sendMsgAxios();
    setState(prevState => ({ ...prevState, callSendMsgAxios: false }) );
  }
}, [callSendMsgAxios]);

...

const sendMsgToMe = () => {
    const { senderIdString, senderId } = props;
    const { messages, counter } = state;
    let myNumber;
    setState(prevState => ({
      ...prevState,
      btnSendMeIsDisabled: true,
    }));
    axios
      .get(`${appConfig.URL_REST}user`, {
        headers: { Authorization: `Bearer ${localStorage.getItem('token')}` },
      })
      .then((response) => {
        myNumber = response.data.phoneNumber;
        setState(prevState => (
          {
            ...prevState,
            callSendMsgAxios: true,
            messageToSend: [
              {
                from: senderIdString ? senderIdString.number : senderId,
                to: myNumber,
                message: messages[counter],
              },
            ],
          }
        ));
      });
  };

...

Upvotes: 1

Emmanuel Ponnudurai
Emmanuel Ponnudurai

Reputation: 1074

The code you put in useEffect, is executed, based on the dependencies you send to it.

So first ask yourself,

  • What should I execute? (Becomes the body of your useEffect)
  • Does it depend on anything before determining if it should execute or not. (Becomes the dependency)
useEffect(() => {
  this.sendMsgAxios(a, b c); // a, b, c could be still thats contained in your state
}, [a, b, c]) // clearly since a, b, c are ones which the effect depends on, you need to pass them in the dependencies array

I'm hoping this will lead to what you want to achieve.

Upvotes: 1

Related Questions