Updated nested value using immer JS

151 Views Asked by At

How is the best way to recursive change a value using a call of recursive function in a Produce of immer? WhatsappState is the general reducer type, Message is the message structure to the application/db.

type WhatsappState = {
  message: Message,
  messages: Message[],
  nextMessage: Message,
  isAuth: boolean,
  qrCode: string,
  modalIsOpen:boolean
}
Message = {
  value: string;
  id: number;
  nextMessage: Message[];
  uid: string;
  messageState: 'create' | 'submessage' | 'edit';
}

Actually i'm trying this way

const submessage = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
    const state = {...WhatsappState, teste: [new Message()]}
    console.table({message: state.message, nextMessage: state.nextMessage})
    console.log(state)
    const newMessage = produce(state, draft => {
      const addMessage = (messages: Array<Message>, uid: string, msg: Message) => {
        for (const message of messages) {
          if (message.uid === uid){
            console.table({message, msg})
            if(!message.nextMessage) message.nextMessage = [];
            message.nextMessage.push(msg)
            return true;
          } else if(addMessage(createDraft(message.nextMessage), uid, msg)){
            return true;
          }
        }
        return false
      }
      addMessage(draft.messages, state.nextMessage.uid, state.message)
    })
    console.log(newMessage);
    WhatsappDispatch({
      type: "set_state",
      payload: { value: newMessage }
    })
    closeModal()
  }

but he don't return the correct produce on newMessage and i receive the follow error modal.component.tsx:65 Uncaught TypeError: Cannot add property 0, object is not extensible at Array.push (<anonymous>)

1

There are 1 best solutions below

0
On

I Founded a way to resolve this question

function saveSubMessage(array: Message[], newMessage: Message, fatherUid: string): any{
  return array.map((item, index) => {
    if (item.uid === fatherUid) {
      return {
        ...item,
        nextMessage: [...item.nextMessage, newMessage]
      }
    }
    if (item.nextMessage && item.nextMessage.length > 0) {
      const nextMessage = saveSubMessage(item.nextMessage, newMessage, fatherUid);
      return { ...item, nextMessage: nextMessage}
    }
    return item;
  })
}
state.messages = saveSubMessage(state.messages, current(state.message), state.nextMessage.uid)
state.message = new Message()
return state;

So, i return the value as assign object to the iteration of nextMessage, i don't know if this is the best way to do that, but for now worked, if exist a better and clean way to make this reply plz.