A React component is a reusable piece of code receiving props to communicate with the outside world.
1. An instance of a component is created.
2. The component’s UI is computed (rendering) and mounted into the DOM.
3. Then an event occurs (e.g. user keystroke) and the already existing component will get new props. The component will be updated and thus will rerender.
4. The component is unmounted (e.g. routing)
Component is ready to mount in the browser
Component is updated in two ways: sending the new props and updating the state
Component is not needed and anmouned from the DOM
constructor()
static getDerivedStateFromError()
render()
componentDidMount()
static getDerivedStateFromError()
render()
componentDidUpdate()
shouldComponentUpdate()
componentWillUnmount()
If you don’t initialize state and you don’t bind methods, you don’t need to implement a constructor.
Most Common Use Case:
constructor(props) {
super(props);
// Don't call this.setState() here!
this.state = { counter: 0 };
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
alert(this.state.message);
}
// you may enable the experimental
// Class Properties syntax proposal with Babel
state = { counter: 0 }
const handleClick = () => handleClick.bind(this);
// Using an arrow here binds the method:
handleClick = () => {
alert(this.state.message);
}
is the only required method in a class component.
When called, it checks this.props and this.state and return one of the following types:
render() won't be invoked if shouldComponentUpdate() returns false
render() {
const {value} = this.props.value;
return (
<input type="button" value={value} onClick={this.logMessage} />
);
React elements.
Arrays and fragments.
Portals.
String and numbers.
Booleans or null.
is invoked immediately after a component is mounted (inserted into the tree)
Most Common Use Case:
componentDidMount() {
fetch(url).then(res => {
// Handle response in the way you want.
// Most often with editing state values.
})
}
this method is meant to be pure and is fired on every render, regardless of the cause.
Most Common Use Case:
If you need to update your state based on a prop changing, you can do it by returning a new state object
class EmailInput extends Component {
state = {
email: this.props.defaultEmail,
prevPropsUserID: this.props.userID
};
static getDerivedStateFromProps(props, state) {
// everytime current user is changes,
// reset state which is linked to this user (email)
if (props.userID !== state.prevPropsUserID) {
return {
prevPropsUserID: props.userID,
email: props.defaultEmail
};
}
return null;
}
// ...
}
answers the question, “should I re-render?”
allows us to say: only update if the props you care about change
Most Common Use Case:
Controlling exactly when your component will re-render.
shouldComponentUpdate(nextProps, nextState)
shouldComponentUpdate(nextProps, nextState) {
return !shallowEqual(nextProps, this.props) || !shallowEqual(nextState, this.state);
}
is invoked right before the most recently rendered output is committed to e.g. the DOM.
It enables your component to capture some information from the DOM (e.g. scroll position) before it is potentially changed.
Most Common Use Case: Taking a look at some attribute of the current DOM, and passing that value on to componentDidUpdate.
getSnapshotBeforeUpdate(prevProps, prevState) {
// Are we adding new items to the list?
// Capture the scroll position so we can adjust scroll later.
if (prevProps.list.length < this.props.list.length) {
const list = this.listRef.current;
return list.scrollHeight - list.scrollTop;
}
return null;
}
is invoked immediately before a component is unmounted and destroyed. Perform any necessary cleanup in this method, such as invalidating timers, canceling network requests, or cleaning up any subscriptions that were created in componentDidMount().
Most Common Use Case:
Cleaning up any leftovers from your component.
componentWillUnmount() {
this.removeClickListener();
this.removeKeyboardListener();
}
static getDerivedStateFromError(error)
Most Common Use Case: Updating state to display an error screen.
A class component becomes an error boundary if it defines either (or both) of the lifecycle methods
are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed
componentDidCatch(error, info)
Most Common Use Case:
Catching and logging errors.
are functions that helps to use state, lifecycle methods and other React features without writing a class.
Motivation
It’s hard to reuse stateful logic between components
Hooks allow to reuse stateful logic without changing component hierarchy.
Complex components become hard to understand
Hooks let to split one component into smaller functions based on what pieces are related
Classes confuse both people and machines
Hooks let to use more of React’s features without classes.
The only argument to useState is the initial state.
function ExampleWithManyStates() {
// Declare multiple state variables!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
// ...
}
side effects
are data fetching, subscriptions, or manually changing the DOM from React components before. We call these operations (or “effects” for short) because they can affect other components and can’t be done during rendering.
Adds the ability to perform side effects from a function component. It serves the same purpose as componentDidMount, componentDidUpdate, and componentWillUnmount in React classes, but unified into a single API.
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
returns a mutable ref object whose .current property is initialized to the passed argument (initialValue).
mutating the .current property doesn’t cause a re-render.
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` points to the mounted text input element
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
handleChange(event) {
this.setState({value: event.target.value});
}
<input
type="text"
value={this.state.value}
onChange={this.handleChange}
/>
function CustomTextInput(props) {
// textInput must be declared here so the ref can refer to it
const textInput = useRef(null);
function handleClick() {
textInput.current.focus();
}
return (
<div>
<input
type="text"
ref={textInput} />
<input
type="button"
value="Focus the text input"
onClick={handleClick}
/>
</div>
);
}
components where the DOM handles the form data
returns a mutable ref object whose .current property is initialized to the passed argument (initialValue).
mutating the .current property doesn’t cause a re-render.
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` points to the mounted text input element
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}