skip to Main Content

I am having an issue with my recipe project. In this section users can add their recipe steps. The user clicks on the plus button to add a textarea to write a new step and clicks on the minus button to remove a step.

The plus button works fine and adds a textarea when clicked, however, the issue I am having is that when the user removes a step the state does not update until the user clicks the plus button again. I am not sure why the minus button does not update straight away like the plus button.

These are the add and remove functions

type Textbox = {
  readonly id: string;
  index: number;
};

 const [textboxes, setTextboxes] = useState<Textbox[]>([]);

 const handleAddTextBox = () => {
    const textbox = {
      id: uniqid(),
      index: textboxes?.length + 1,
    };

    const allTextBoxes = [...textboxes, textbox];
    setTextboxes(allTextBoxes);
  };

  const handleRemoveTextBox = () => {
    if (textboxes.length <= 1) {
      alert("You need at least one step. Try being more descriptive.");
    } else {
      textboxes.pop();
    }
  };

This is where I implement them

<section className={`${styles.section5} ${styles.section}`}>
            <div className={styles.field}>
              <h1 className={styles.label}>instructions</h1>
              <div className={styles["step-list"]}>
                {textboxes.map((box: { id: string; index: number }) => (
                  <div className={styles.step} key={box.id}>
                    <label htmlFor={box.id} className={styles.index}>
                      step {box.index}
                    </label>
                    <textarea
                      name={box.id}
                      id={box.id}
                      cols={100}
                      rows={3}
                      className={styles.textbox}
                      ref={instructionRef}
                    ></textarea>
                  </div>
                ))}
              </div>

              {/* Add textbox button */}
              <button
                className={`${styles.icon} ${styles.add}`}
                onClick={handleAddTextBox}
                type="button"
              >
                <i className="fa-solid fa-plus"></i>
              </button>

              {/* Remove textbox button */}
              <button
                className={`${styles.icon} ${styles.remove}`}
                onClick={handleRemoveTextBox}
                type="button"
              >
                <i className="fa-solid fa-minus"></i>
              </button>
            </div>
          </section>

I have also included a link to my GitHub repo where you can view the rest of my source code incase this is not enough or something else I am doing is affecting my problem. Go to src/components/Post/PostForm.tsx to view the relevant code.
source-code

2

Answers


  1. textboxes is a reference for react’s signal created by useState() those. It is a mutable array, but react does not have two-way data binding like Angular.

    Once you modified the array, you have to call setTextboxes(newArray) to update the UI.

    
    function removeBox() {
     // ....
     textboxes.pop()
     setTextboxes(textboxes)
    }
    
    
    Login or Signup to reply.
  2. You need to setTextboxes inside your handleRemoveTextBox function in order to update the state.

    const handleRemoveTextBox = () => {
        if (textboxes.length <= 1) {
           alert("You need at least one step. Try being more descriptive.");
        } else {
           textboxes.pop();
           setTextboxes(textboxes);
        }
    }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search