0

I've been trying for a long time to implement the function to update my transactions, but I can't type in the input. I saw several similar questions on stackoverflow, but NONE helped me, I'm using modal and I believe the problem is because I'm receiving an object and I'm trying to manipulate another. However, I am not able to solve. Can anyone tell me how to proceed and explain a little how to avoid this?

My TransactionTable:

interface Transaction {
  id: string;
  title: string;
  amount: number;
  type: string;
  category: string;
  createdAt: string;
}

export function TransactionsTable() {
(...)
  const [editingTransaction, setEditingTransaction] = useState<Transaction>()

  function onOpenUpdateTransactionModal(transaction: Transaction) {
    setEditingTransaction(transaction)
    setIsUpdateTransactionModalOpen(true)
  }

  return (
     (...)
      <PencilSimple
                size={20}
                weight="fill"
                onClick={() => onOpenUpdateTransactionModal(transaction)}
       />
       (...)
      <UpdateTransactionModal
        isOpen={isUpdateTransactionModalOpen}
        onRequestClose={onCloseUpdateTransactionModal}
        editingTransaction={editingTransaction}
      />
  )
}

My UpdateTransactionModal:

interface UpdateTransactionModalProps {
  isOpen: boolean;
  editingTransaction: Transaction | undefined;
  onRequestClose: () => void;
}

export function UpdateTransactionModal({ isOpen, onRequestClose, editingTransaction }: UpdateTransactionModalProps) {
   (...)
  const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
    if(event.target.name === 'title') {
      setTitle(event.target.value)
    }

   return(
      (...)
     <S.Container onSubmit={handleUpdateTransaction}>

        <h2>Atualizar transação</h2>

        <input
          type="text"
          placeholder="Título"
          name="title"
          value={editingTransaction?.title}
          onChange={handleInputChange}
        />

        <input
          type="number"
          placeholder="Valor"
          value={editingTransaction?.amount}
          onChange={e => setTitle(e.target.value)}
        />

   )
  }
}

I omitted a good part of the code, as I assumed it wasn't part of the resolution and didn't want to prolong the question, but if you want to see the whole code, it's here:

https://github.com/eltonsantos/eurorcamento

4
  • On change, you call setTitle, which doesn't modify editingTransaction.title, which is what you set the input value to be. You pass in editingTransaction as a prop, if you want to do this, you need to communicate to the parent component that editingTransaction has changed. Commented Dec 13, 2022 at 6:37
  • Can you add the test user creds? I have set up a codespace from you git repo Commented Dec 13, 2022 at 6:43
  • @DreamBold sure, a minute Commented Dec 13, 2022 at 6:44
  • dreambold-bookish-fiesta-ppx497jj9v5h6j69-3000.preview.app.gith… Commented Dec 13, 2022 at 6:44

1 Answer 1

2
import { ChangeEvent, FormEvent, useEffect, useState } from 'react';
import Modal from 'react-modal';

import incomeImg from '../../assets/income.svg';
import outcomeImg from '../../assets/outcome.svg';
import closeImg from '../../assets/close.svg';

import * as S from './styles';

import { useTransactions } from '../../hooks/useTransactions';

interface Transaction {
  id: string;
  title: string;
  amount: number;
  type: string;
  category: string;
  createdAt: string;
}

interface UpdateTransactionModalProps {
  isOpen: boolean;
  editingTransaction: Transaction | undefined;
  onRequestClose: () => void;
}

export function UpdateTransactionModal({ isOpen, onRequestClose, 
editingTransaction }: UpdateTransactionModalProps) {

 const { updateTransaction } = useTransactions()
 const [transaction, setTransaction] = useState({
    title: editingTransaction?.title,
    amount: editingTransaction?.amount,
    type: editingTransaction?.type,
    category: editingTransaction?.category
  })
 useEffect(() => {
   setTransaction({...transaction, title: editingTransaction?.title, 
amount: editingTransaction?.amount, type: editingTransaction?.type, 
category: editingTransaction?.category})
  },[editingTransaction])
  console.log(editingTransaction)
  console.log(transaction);

 async function handleUpdateTransaction(event: any) {
    event.preventDefault();
    console.log("UpdID" + editingTransaction)
    // await updateTransaction()
    //setEditingTransaction(editingTransaction)
  }

  const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
    setTransaction({...transaction, [e.target.name]: e.target.value});
  }

  return (
<Modal
  isOpen={isOpen}
  onRequestClose={onRequestClose}
  overlayClassName="react-modal-overlay"
  className="react-modal-content"
>
  <button
    type="button"
    onClick={onRequestClose}
    className="react-modal-close"
  >
    <img src={closeImg} alt="Fechar modal" />
  </button>

  <S.Container onSubmit={handleUpdateTransaction}>

    <h2>Atualizar transação</h2>

    <input
      type="text"
      placeholder="Título"
      name="title"
      value={transaction.title}
      onChange={handleInputChange}
    />

    <input
      type="number"
      placeholder="Valor"
      value={transaction.amount}
      onChange={handleInputChange}
    />

    <S.TransactionTypeContainer>
      <S.RadioBox
        type="button"
        isActive={transaction?.type === 'deposit'}
        activeColor="green"
        onClick={() => {setTransaction({...transaction, type: 'deposit'})}}
      >
        <img src={incomeImg} alt="Entrada" />
        <span>Entrada</span>
      </S.RadioBox>
      <S.RadioBox
        type="button"
        isActive={transaction?.type === 'withdraw'}
        activeColor="red"
        onClick={() => {setTransaction({...transaction, type: 'withdraw'})}}
      >
        <img src={outcomeImg} alt="Saída" />
        <span>Saída</span>
      </S.RadioBox>
    </S.TransactionTypeContainer>

    <input
      type="text"
      placeholder="Categoria"
      value={editingTransaction?.category}
      onChange={handleInputChange}
    />

    <button type="submit">Atualizar</button>
  
  </S.Container>
</Modal>

) }

This is your updated code for updateTransactionModal. The Problems:

  • You were passing value from editingTransactions to the input value field. That is why value was not updating.
  • Secondly you were setting setTitle for all fields. either you can call setTitle, setAmount and so on for each field or you can simply create a transaction object and set them as i did in the code above.
  • Third problem: Your value from editTransaction was undefined when the component loads for first time. and it gets updated a second later which leads to empty fields once you use the state value in your input fields. In order to solve that we applied a useEffect which updates the state with the updated editTransaction value. But you need to check why this is happening and avoid this. The editTransaction should be passed into the model as a prop and it should get the latest value on the first load there should be no need for useEffect. Hope I was able to solve.
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.