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>
);
}
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.
css modules || CSS in JS || global stylesheets
// App.tsx
import './App.css';
We will implement all of this in App.tsx for now.
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?
Every component can have its own state.
The component is always derived from its state - there is a unidirectional data flow.
You must use the [state, setState] hooks to tell React that something has changed and the component needs to be rerendered.
function MyComponent() {
const [name, setName] = useState('');
function onUpdateName(name) {
setName(name);
}
return (
...
)
}
Since our header is a separate component, we need a way to pass name to it.
<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>
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);
<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');