0

I have an app like this

function App(){
    const [appState, setAppState] = useState(
        {
            questions: []
        }
    )

    const addToQuestion = (questionObject) =>{

        setAppState((prevState) => {
            return {...prevState, questions: [...prevState.questions, questionObject]}
        })

    }

    let removeFromQuestionArray = () => {
        setAppState((prevState) => {
            let a = prevState.questions
            a.pop()
            return {...prevState, questions: a}
        })
    }

    const onBackButtonClicked = () => {
        removeFromQuestionArray()
    }
}

But when I call removeFromQuestionsArray() the setAppState works unpredictably. It sometimes removes all the items in the array even though I'm only popping the last item in the array. What could be causing this. I just want to remove the last item from the array, how can I go about this without having issues?

FlashspeedIfe
  • 368
  • 1
  • 6
  • 15

1 Answers1

1

Your code works fine.

Posting this as an answer to show the snippet:

Note: I edited the addToQuestions function to make it work for the example, but I didn't touch removeFromQuestionsArray

const { useState, useRef } = React

function App(){
    const [appState, setAppState] = useState(
        {
            questions: [
              'What is Love',
              'Whats the meaning of life',
              'Whats the answer to this question'
            ]
        }
    )
    
    const input = useRef();

    const addToQuestion = () =>{
        let question = input.current.value;
        setAppState((prevState) => {
            return {...prevState, questions: [...prevState.questions, question]}
        })
        input.current.value = '';
        input.current.focus();

    }

    let removeFromQuestionArray = () => {
        setAppState((prevState) => {
            let a = prevState.questions
            a.pop()
            return {...prevState, questions: a}
        })
    }
  return (
  <div>
    {appState.questions.map(question => <li>{question}</li>)}
    <input ref={input}></input>
    <button onClick={addToQuestion}>Add Question</button>
    <button onClick={removeFromQuestionArray}>Remove</button>
  </div>
  )
}

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
,
  root
)
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Brother58697
  • 2,290
  • 2
  • 4
  • 12
  • In addToQuestion the line input.current.value throws Uncaught TypeError: Cannot read properties of undefined (reading 'value'). – FlashspeedIfe Aug 11 '22 at 12:03
  • Are you getting that error when running it from the snippet? – Brother58697 Aug 11 '22 at 12:06
  • No, its when I have it in my IDE. – FlashspeedIfe Aug 11 '22 at 12:08
  • Make sure you import `useRef` even though that'd give a different error if you hadn't. And make sure you set the `ref` property of the input element to `input` which is declared after the state: `` – Brother58697 Aug 11 '22 at 12:10
  • Your version works in the code snippet but you haven't changed anything in the removeQuestionsFromArray that would cause the state update to not be made multiple times undesirably. – FlashspeedIfe Aug 11 '22 at 12:11
  • Exactly, to show that the original version in your question doesn't act undesirably. – Brother58697 Aug 11 '22 at 12:11
  • I'm not sure how useRef addresses the issue, could you pls fill me in? I know its used to persist data between renders but I'm not much informed on it. – FlashspeedIfe Aug 11 '22 at 12:13
  • Its weird because when I run it and inspect the state in chrome using the React Developer Tools the items in the array get removed undesirably and logging to the console shows multiple calls to the setAppState is made causing more than one item to be removed from the array. – FlashspeedIfe Aug 11 '22 at 12:15
  • Try to recreate the issue in this [Code Sandbox](https://codesandbox.io/s/new?file=/src/index.js) and post it here or in the question, I'd be happy to look at it. – Brother58697 Aug 11 '22 at 12:18
  • Maybe this is a clue. https://stackoverflow.com/a/61897567/4268050 I was just reading react invokes the App Component twice but only in dev mode to find problems with the code if there are any when StrictMode is on. – FlashspeedIfe Aug 11 '22 at 12:19
  • It shouldn't be a problem because `setAppState` doesn't run when the component re-renders. Do you have any effect hooks (`useEffect`) anywhere else in the ocmponenet? – Brother58697 Aug 11 '22 at 12:20
  • No I've not got any effect hooks at all. – FlashspeedIfe Aug 11 '22 at 12:45
  • Hmmm, try recreating the issue in the sandbox, it'll help debug it – Brother58697 Aug 11 '22 at 13:03