Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the proper way to use React Memo with Flow?

This line of code

export default memo(LoadingOverlay);

Gives flow error

Missing type annotation for `P`. `P` is a type parameter declared in  function type [1] and was implicitly instantiated at  call of `memo` [2].Flow(InferError)

And this line

export default memo<TProps>(LoadingOverlay);

Gives compile time error. What's the proper use of React memo with flow?

EDIT:

Here is the full file example

// @flow

// React modules
import React, { memo } from 'react';

// Material UI components
import Checkbox from '@material-ui/core/Checkbox';
import FormControlLabel from '@material-ui/core/FormControlLabel';

// Utils and defaults
import './checkbox.scss';

type TProps = {
  value: string;
  label: string;
  checked: boolean;
  disabled?: boolean;
  onChange: Function;
};

/*
 * Presentational component with following props:
 *  value: String, value as a name of checkbox
 *  label: String, checkbox label
 *  checked: Boolean, checkbox state
 *  disabled: Boolean, checkbox availability state
 */
const Checkbox = (props: TProps) => {
  console.log('RENDER CHECKBOX');
  const {
    value,
    label,
    checked,
    disabled
  } = props;
  const { onChange } = props;

  return (
    <FormControlLabel
      control={
        <Checkbox
          checked={checked}
          onChange={onChange(value)}
          value={value}
          disabled={disabled}
          color="primary"
        />
      }
      label={label}
    />
  );
};

Checkbox.defaultProps = {
  disabled: false,
};

export default memo<TProps>(Checkbox);
like image 460
Hayk Safaryan Avatar asked Dec 20 '18 06:12

Hayk Safaryan


People also ask

How do you use React memo in React JS?

Useful when you expect the same result from a component: you should wrap a component in your React app to React Memo when you know beforehand that it will render the same result to the DOM when given the same props to it. Thereby, it will result in a performance boost as it will memoize the result.

Should you use memo React?

Strictly use React. memo() as a performance boost for applications with components that re-render often. However, keep in mind that React components will always re-render if the state changes — regardless of whether the component is wrapped in React.

Why React memo is used?

Using memo will cause React to skip rendering a component if its props have not changed. This can improve performance.

What is true about React memo?

memo is a higher order component. If your component renders the same result given the same props, you can wrap it in a call to React. memo for a performance boost in some cases by memoizing the result. This means that React will skip rendering the component, and reuse the last rendered result.


2 Answers

I have got the same problem. The problem is not with the Flow but with Babel.

React.memo with Flow

You have got it right. Correct approach really is:

export default memo<Props>(MyComponent);

Compilation problem

There are two ways to solve that.

1. Simple: Adding flow annotation to the top

Add // @flow to the top of the file. The error comes from Babel and it needs the annotation there. Even though you might have all=true in .flowconfig (and Flow work perfectly) you need to do that.

Useful when using create-react-app and do not want to eject.

2. Configuring Babel

Add Babel preset for Flow and specify "all": true option to your .babelrc:

{   
  "presets": [
    ["@babel/preset-flow", {
      "all": true
    }]
  ]
}

However, this needs anyone using create-react-app to eject. (Or might use react-app-rewired but I have no experience with that.)

This solution is mentioned on here (thanks @fl0shizzle for mentioning it) and for discussion about create-react-app solution look on here.

like image 102
exmaxx Avatar answered Sep 23 '22 22:09

exmaxx


Make sure you have the latest version of flow. When I updated my flow version it just worked. I was missing the // @flow at the top so had to add all=true to my preset config.

like image 34
Alex Gurr Avatar answered Sep 22 '22 22:09

Alex Gurr