3

I have a project that I am going to add tags, similar to this site. I want to first check if the tag has already been selected by the user. I have a for loop to see if the tag added equals the tags that are already there.

If I make a tag named Jack, it will work just fine. If I create another tag named Jack, now I have two Jacks(not good). On the third attempt, it doesn't add another Jack (good.)

Here is my relevant code. I have added the console as well. My useState setTagAlreadyThere on is being ignored until the third attempt, when it should go to true on the second attempt. What am I doing wrong here?

const [tagsFound, setTagsFound] = useState([])
const [tagsAdded, setTagsAdded] = useState([])    
const [tagAlreadyThere, setTagAlreadyThere] = useState(false)

const gatherTags = (tags) => {
    setTagAlreadyThere(false)
    console.log(tagAlreadyThere)

    if (tagsAdded.length === 0) {
        setTagsAdded([...tagsAdded, tags]);
    } else {
        console.log(tagsAdded)

        for (let i = 0; i < tagsAdded.length; i++) {
            console.log(tagsAdded[i])

            if (tags === tagsAdded[i]) {
                console.log(tagsAdded[i])
                console.log(tags)
                setTagAlreadyThere(true)
                console.log(tagAlreadyThere)
            }
        }
        console.log(tagAlreadyThere)
        if (tagAlreadyThere === false) {
            setTagsAdded([...tagsAdded, tags]);
            console.log(tagsAdded)
        } else {
            return
        }
    }

    setPostTag('')
}

Console.

TagAdder.tsx:9 jack
postarticle.tsx:64 false
postarticle.tsx:69 ["jack"]
postarticle.tsx:72 jack
postarticle.tsx:75 jack
postarticle.tsx:76 jack
postarticle.tsx:78 false
postarticle.tsx:81 false
postarticle.tsx:84 ["jack"]
post.tsx:6 {}
postarticle.tsx:92 (2) ["jack", "jack"]
post.tsx:6 {}
postarticle.tsx:

92

2
  • Where is your hooks? Commented Aug 31, 2019 at 3:45
  • just useState. I'll post Commented Aug 31, 2019 at 3:50

2 Answers 2

2

no offense but you code has so many unnecessary stuff.

So why it is happening. Because you tagAlreadyThere is not updated yet. And you are checking it is value.

const gatherTags = (tags) => {
    if (!tagsAdded.inlcudes(tags)) {
      setTagsAdded([...tagsAdded, tags]);
      setPostTag('')
    }
}

No need for const [tagAlreadyThere, setTagAlreadyThere] = useState(false)

Sign up to request clarification or add additional context in comments.

1 Comment

Offense? No sir, I totally agree with you. I'm still learning, about a year in, and am trying super hard to get my code tighter. I appreciate your AWESOME answer!
1

I will give you an idea on why this code causes a lot of issues, no offense.

First is you call a hook inside a loop synchronously, because React.useState hook is asynchronous just like this.setState in class-based and it batches updates to gain performance.

I have an example here on Code Sandbox: Calling Hooks Sync and Async

Second is if your new state is computed from the previous state, use the callback style because you can access the updated previous state, example:

setTagsAdded(prevTagsAdded => [...prevTagsAdded, tags])

You can check the documentation here: Functional Updates

Hope this helps!

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.