Refactoring React¶
State that depends first on props
and then on useEffect
💩¶
GET /dashboard/<ID>
will get a JSON response
GET /dashboard
will get the same JSON response
const DashboardRenderer = ({ urlId }) => {
// init
const [backendId, setBackendId] = useState(urlid);
const dashboard = useSelector({dashboards} => dashboards[backendId]);
const dispatch = useDispatch();
useEffect(() => {
loadDashboard(dispatch, backendId).then(({ data }) => {
setBackendId(data.id);
});
});
}, [dispatch, backendId]);
- First render:
urlId
isnull
useEffect
is called- It sets the
backendId
state which triggers a re-render
- It sets the
- Second re-render: runs the
useEffect
again- makes another API call
How to only make one API call?
Solution: only use the prop
in the useEffect
¶
const DashboardRenderer = ({ urlId }) => {
// init
const [backendId, setBackendId] = useState(urlId);
const dashboard = useSelector({dashboards} => dashboards[backendId]);
const dispatch = useDispatch();
useEffect(() => {
- loadDashboard(dispatch, backendId).then(({ data }) => {
+ loadDashboard(dispatch, urlId).then(({ data }) => {
setBackendId(data.id);
});
});
- }, [dispatch, backendId]);
+ }, [dispatch, urlId]);
UnknownObject
as a dependency in useEffect
¶
It makes an API call every time 😞
- when a new object is created
- it has a new pointer
const Component = ({queryParams}) => {
useEffect(() => {
fetch("example.com?" + new URLSearchParams(...queryParams));
}, [queryParams]);
...
};
Solution¶
- Store the serialized (
JSON.stringify
) object’s previous value - If the current serialized value is different than before
- make an API call
const Component = ({ queryParams }) => {
const previousValue = usePrevious(JSON.stringify(queryParams));
useEffect(() => {
if (JSON.stringify(queryParams) !== previousValue) {
fetch("example.com?" + new URLSearchParams(...queryParams));
}
}, [queryParams]);
};
Don't need the undefined
Returning undefined¶
Components can't return undefined
It was a way to catch errors
- since you likely didn't mean to return undefined
- likely forgot a return statement
- or forgot to return something
- if you don't want to render anything, you can return null
function MyComp() {
const canView = useFeatureToggle('feature');
- return canView && <div>Hi</div>
+ return canView ? <div>Hi</div> : null
}
components rendering undefined
Last update:
2023-04-24