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.useState does not Reload State from Props
React.useState
doesn’t reload state from props.
It can only set the initial state.
If we need to update the state as props change, then we need to use the useEffect
hook.
For instance, we can write:
function Avatar({ username }) {
const [name, setName] = React.useState(username);
React.useEffect(() => {
setName(name);
}, [username])
return <img src={`${name}.png`}/>
}
We get the username
prop .
And we set it as the initial value of the name
state with useState
.
Then we use the useEffect
hook to watch for changes in the name
value.
We watch it for changes, then call setName
to set the name with the latest value of username
as the name
‘s new value.
Then we can use name
in the JSX we render.
Use for useCallback
We can use useCallback
to cache the callback so that we don’t call a create a new instance of the callback function on every render.
For instance, instead of writing:
function Foo() {
const handleClick = () => {
console.log('clicked');
}
<button onClick={handleClick}>click me</button>;
}
We write:
function Foo() {
const memoizedHandleClick = useCallback(
() => console.log('clicked'), [],
);
return <Button onClick={memoizedHandleClick}>Click Me</Button>;
}
The useCallback
hook caches the click callback so that the same instance is used on every render instead of creating a new one.
Detect a React Component vs. a React Element
We can check if an object is a function component by checking that it’s a function and that it contains the 'return React.createElement'
code.
For instance, we can write:
const isFunctionComponent = (component) => {
return (
typeof component === 'function' &&
String(component).includes('return React.createElement')
)
}
To check for a class component we can check for type 'function'
.
And we can check for the isReactComponent
property in the component’s prototype
.
For example, we can write:
const isClassComponent = (component) => {
return (
typeof component === 'function' &&
!!component.prototype.isReactComponent
)
}
To check if a variable is a valid element, we can use the React.isValidElement
method to do that.
For example, we can write:
const isElement = (element) => {
return React.isValidElement(element);
}
React Hooks useEffect() Cleanup When Component Unmounts
We can return a function in the useEffect
callback to return a function that runs our clean up code.
For example, we can write:
const { useState, useEffect } = React;
const ForExample = () => {
const [name, setName] = useState("");
const [username, setUsername] = useState("");
useEffect(
() => {
console.log("do something");
},
[username]
);
useEffect(() => {
return () => {
console.log("cleaned up");
};
}, []);
const handleName = e => {
const { value } = e.target;
setName(value);
};
const handleUsername = e => {
const { value } = e.target;
setUsername(value);
};
return (
<div>
<div>
<input value={name} onChange={handleName} />
<input value={username} onChange={handleUsername} />
</div>
</div>
);
};
We have our change event handlers.
And we have our useEffect
calls.
They all have their own callbacks.
The first one watches for changes in the username
function.
In the 2nd one, the callback returns a function that runs code when the component unmounts.
React Router Redirect after Redux Action
We can redirect after a Redux action is committed.
To do that, we install the history
package.
We install it by running:
npm install --save history
Then we can create a function like:
import { createBrowserHistory } from 'history';
const browserHistory = createBrowserHistory();
const actionName = () => (dispatch) => {
axios
.post('url', { body })
.then(response => {
dispatch({
type: ACTION_TYPE_NAME,
payload: payload
});
browserHistory.push('/foo');
})
.catch(err => {
// Process error code
});
});
};
We make a POST request with Axios.
Then in the then
callback, we call dispatch
to dispatch our actions.
And then we call browserHistory.push
to navigate.
We called createBrowserHistory
to get the browserHistory
object.
Conclusion
We use the useEffect
hook to update our values.
It can also be used to run clean up code when a component unmounts.
If we need to navigate to another route after a Redux action is done, we can use the browserHistory.push
method to do that after we dispatched our action.