React is a popular library for creating web apps and mobile apps.
In this article, we’ll look at some tips for writing better React apps.
React Batch State Update Batching with Hooks
If the state changes and triggered asynchronously, then they won’t be batched.
On the other hand, if they’re triggered directly, then they’ll be batched.
For instance, if we call multiple state change functions within a promise, then they won’t be batched:
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
function Component() {
const [foo, setFoo] = useState('a');
const [bar, setBar] = useState('b');
const handleClickPromise = () => {
Promise.resolve().then(() => {
setFoo('aa');
setBar('bb');
});
}
return (
<>
<button onClick={handleClickPromise}>
click me
</button>
<p>{foo} {bar}</p>
</>
);
}
If the state change functions are called in a promise as we have in the then
callback, then they won’t be batched.
On the other hand, if we have:
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
function Component() {
const [foo, setFoo] = useState('a');
const [bar, setBar] = useState('b');
const handleClick = () => {
setFoo('aa');
setBar('bb');
}
return (
<>
<button onClick={handleClick}>
click me
</button>
<p>{foo} {bar}</p>
</>
);
}
Then they’ll be batched.
If they’re batched, then the updates will show up immediately.
Conditional Rendering in styled-components
To render something conditionally with a component created with styled-components, we can pass in a function into the string with the props as the parameter.
For instance, we can write:
const Button = styled.button`
width: 100%;
outline: 0;
border: 0;
height: 100%;
justify-content: center;
align-items: center;
line-height: 0.2;
${({ active }) => active && `
background: green;
`}
`;
We have a bunch of static styles.
In the end, we have a function that takes the active
prop.
Then we return 'background: green'
with active
is true
.
The styled.button
template tag is a function that’ll convert the style string to a component with the styles.
And then can use it by writing:
<Button active={this.state.active}></Button>
We can also add conditional styles to an existing component by writing:
const StyledFoo = styled(Foo)`
background: ${props => props.active ? 'blue' : 'green'}
`
We use the styled
function which takes a component and returns a template tag.
Then we create a string with a function interpolated in it that takes the props and returns 'blue'
or 'green'
depending on if the active
prop is true
or not.
Only Allow Children of a Specific Type in a React Component
To allow children of a specific type in a React component, we can loop through each entry of children
and then throw an error if we see something we don’t want.
To do that, we can create a custom validation function in the object that we set as the value of the propTypes
property.
For instance, we can write:
class ItemGroup extends Component {
render() {
return (
<div>{this.props.children}</div>
)
}
}
ItemGroup.propTypes = {
children(props, propName, componentName) {
const prop = props[propName]
let error = null
React.Children.forEach(prop, (child) => {
if (child.type !== Item) {
error = new Error(`${componentName} children should be Items`);
}
})
return error;
}
}
We created our own prop validation method to validate the children
prop.
We get all the children with React.children
and call forEach
on it to loop through each item.
In the callback, we get the child
element that we’re looping through and we can check the type of it with the type
property.
If it doesn’t return something of type Item
, we set the error
and return it.
Prevent Multiple Button Presses with React
To prevent multiple button presses with React, we can use the disabled
prop to disable the button after we clicked the button.
For instance, we can write:
class App extends React.Component {
this.state = {
disabled : false
};
handleClick = (event) => {
if (this.state.disabled) {
return;
}
this.setState({ disabled: true });
}
render() {
return (
<button onClick={this.handleClick} disabled={this.state.disabled}>
{this.state.disabled ? 'Sending...' : 'Send'}
<button>
);
}
We have the handleClick
method that checks the disabled
state.
If it’s true
, we do nothing.
Otherwise, we set thedisabled
state to true
and the button will be disabled because we passed that value to the disabled
prop.
Conclusion
We can disable buttons on click with the disabled
prop.
State updates are batched if they’re called synchronously in function components.
Styling can be done conditionally with styleled-components.