React Essentials
03 Your First Components

What is a Component?

Components let you split the UI into independent, reusable pieces, and think about each piece in isolation

In React, a component is simply a function that returns JSX.

                    
                        Definition:

                        function Header() {
                            return <h1>Hello, Freddie</h1>
                        }
                    
                
                    
                        Usage:

                        <Header />
                    
                

Multiline JSX should always be wrapped in braces.

                    
                        function Content() {
                            return (
                                <div>
                                  <p>Some nice content</p>
                                </div>
                            );
                        }
                    
                

Rough Page Layout

Let's give our app some layout. At first, you can just create all components in App.tsx

                    
                        <Header />
                        <h1>Hello Content</h1>
                        <Footer />
                    
                

Once it's working, you can move them into separate files.

Styling

css modules || CSS in JS || global stylesheets

Global Stylesheet

                    
                        // App.tsx
                        import './App.css';
                    
                

Registration

  • Show "Hello, stranger" initially.
  • Provide an input field where the user can enter their name.
  • Provide a button to confirm the input.
  • Show "Hello, name" when the user confirms the input.

We will implement all of this in App.tsx for now.

Hints

                    
                        let name = '';

                        <input onChange={(event) => ...} />

                        <span>hello, {name || 'stranger'}</span>
                    
                

Does the component display the updated name correctly?

How does React know it should rerender?

Introducing State

Every component can have its own state.

The component is always derived from its state - there is a unidirectional data flow.

The useState hook

You must use the [state, setState] hooks to tell React that something has changed and the component needs to be rerendered.

The useState hook

                    
                        function MyComponent() {
                            const [name, setName] = useState('');

                            function onUpdateName(name) {
                                setName(name);
                            }

                            return (
                                ...
                            )
                        }
                    
                

Displaying the user name in the header

Since our header is a separate component, we need a way to pass name to it.

Introducing props

                    
                        <Header name={name} />
                    
                
                    
                        function Header(props) {
                            return <h1>{props.name}</h1>;
                        }
                    
                

Refactor your App to display the name in the header instead of the content.

Let's introduce a confirm button. Only update the name when that button is clicked.

                    
                        <button onClick={() => ...}>Confirm</button>
                    
                

Testing

jest && react-testing-library

Testing library's philosophy

Test components from a user's perspective and don't test implementation details.

                    
                        // don't
                        component.instance().addItem('MacBook Pro');
                        expect(component.state.shoppingCart.length).toBe(1);
                    
                
                    
                        // do
                        component.find('.add-item-button').click();
                        expect(component.find('.cart-item').length).toBe(1);
                    
                

RTL API

                    
                        <button data-testid="confirm">Confirm</button>
                        <input data-testid="input" />
                        <span data-testid="display">...</span>
                    
                
                    
                        const component = render(<App />);
                        const input = component.getByTestId('input');
                        const btn = component.getByTestId('confirm')
                        const display = component.getByTestId('display');

                        fireEvent.change(input, 'John');
                        fireEvent.click(btn);
                        expect(display.innerHTML).toBe('John');
                    
                

Questions?