DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for How to build a search bar in React

How to build a search bar in React

Emma Goto πŸ™ on November 05, 2020

A search bar is a great way to make content on your website discoverable. In this tutorial, we’ll be building an accessible search bar component us...
Collapse
 
wannabehexagon profile image
ItsThatHexagonGuy

Hello Emma! Loved the accessibility topics, I love axe and I was happy you mentioned it :)

Quick nit: Don't pass setters to child components, this allows a child component to freely mutate the state of the parent. Children should only react to changes and then mutate the state of a parent accordingly. That way the data flow is predictable.

Collapse
 
emma profile image
Emma Goto πŸ™

Hi, thanks for the feedback - do you have suggestions on how you would approach this instead?

Collapse
 
wannabehexagon profile image
ItsThatHexagonGuy • Edited on

First off what you did wasn't wrong, with that in mind read the following from the React docs:

There should be a single β€œsource of truth” for any data that changes in a React application. Usually, the state is first added to the component that needs it for rendering. Then, if other components also need it, you can lift it up to their closest common ancestor. Instead of trying to sync the state between different components, you should rely on the top-down data flow.

Lifting state involves writing more β€œboilerplate” code than two-way binding approaches, but as a benefit, it takes less work to find and isolate bugs. 
Enter fullscreen mode Exit fullscreen mode

So, the idea is to only have the parent have full control over the state, the child should receive the parent's state and control to that state as props. This way if there's a bug, you always know where to look for - the parent. You can grant control to the state via props by wrapping the setter in a function in the parent. Doing so will also allow you to control how the child mutates the parent's state too.

TLDR: Wrapping the setter in a function and passing it as a prop, then calling it in the child makes it look like the parent is changing the state, not the child.

Thread Thread
 
emma profile image
Emma Goto πŸ™

Makes sense, thanks for the detailed explanation :)

Collapse
 
faiwer profile image
Stepan Zubashev

Mydrax:

const [searchValue, setSearchValue] = useState('');

// 1
return <SearchInput onChange={setSearchValue}/>

// 2
const onChange = (newValue: string) => {
  setSearchValue(newValue);
};

return <SearchInput onChange={setSearchValue}/>;
Enter fullscreen mode Exit fullscreen mode

Do you mean this? I think it's just another one level of bureaucracy. The only difference is that you cannot do this with the wrapper:

onChange(prevValue => ...)
Enter fullscreen mode Exit fullscreen mode

But if you use TypeScript and will declare prop-type like:

onChange: (newValue: stirng): void
Enter fullscreen mode Exit fullscreen mode

you would not be able to do it anyway

I think it's more than "okay" to pass setters below the tree. And it doesn't violate top-down principle. The parent component in both cases is the only source of truth. And the only way to change the state is to use those tools that parent components provide to its children.

P.S. also if you're interested in strong performance you will wrap you wrapper by another wrapper (useCallback) :)

Collapse
 
starboysharma profile image
Pankaj Sharma

Hello Emma! πŸ˜€ Thank you for this tutorial. I have also implemented a search 🧐 in react. But I am using a different approach. 🀯 I think my code is a bit shorter. Please share your thoughts. As I am new in react and still I am learning πŸ˜…πŸ˜….

dark-todo.netlify.app/
My Code: github.com/Starboy-Sharma/react-to...

Collapse
 
fiik346 profile image
Taufik Nurhidayat

I want to try, but i use vue :D

Collapse
 
emma profile image
Emma Goto πŸ™

I'm sure some of this is probably quite similar to Vue - especially the accessibility bits!

Collapse
 
vaibhavkhulbe profile image
Vaibhav Khulbe

That's a great breakdown! Will feature this article in my newsletter. 😍

Collapse
 
emma profile image
Emma Goto πŸ™

Wow that's awesome! I'll make sure to subscribe :)

Collapse
 
vaibhavkhulbe profile image
Vaibhav Khulbe

Thank you so much!

Collapse
 
lexswed profile image
Lex Swed

Thank you, Emma! Very good read!

Collapse
 
indoor_keith profile image
Keith Charles • Edited on

This is so great. One of the first mini how-to's that goes this far in-depth on the accessibility aspect of components. I love it, thanks so much for sharing!

Collapse
 
emma profile image
Emma Goto πŸ™

Thanks Keith! I had to do a lot of Googling to try and find out the answers to my accessibility questions - definitely an area of improvement for all of us as developers!

Collapse
 
andrewbaisden profile image
Andrew Baisden

Nice seems to work well.

Collapse
 
dmahely profile image
Doaa Mahely

Highly informative post, will be coming back to it. Great job πŸ‘

Collapse
 
emma profile image
Emma Goto πŸ™

Thanks Doaa, glad you like it!

Collapse
 
bevis profile image
Bevis

Thanks for sharing! Happy to see that works on accessibility, so niceπŸ‘πŸ‘πŸ‘

Collapse
 
marchiartur profile image
aRTUR

Thanks for this post!!