Today I Learned

24 posts about #react

Configure graphql syntax highlighting in VS Code

Initially, gql query/mutation are displayed as regular strings.

GraphQL file without syntax highlighting

To enable syntax highlighting, autocompletion, and validation for graphql query/mutation definition in VSCode follow few steps.

. .

Step 1

Open Extensions tab in your VS Code and install GraphQL plugin

GraphQL plugin for VS Code

. .

Step 2

Create a new file graphql.config.json file in your project’s root folder.

{
  "name": "Name of your Project",
  "schemaPath": "./schema.json",
  "extensions": {
    "endpoints": {
      "Default GraphQL Endpoint": {
        "url": "URL_to_your_graphql",
      }
    }
  }
}

. .

End result

Now you should have syntax highlighting, autocompletion, and validation in your graphql files based on your graphql schema

end_result

. .

Additioanl info

Any problems with the setup? Please check out the plugin documentation

If you’re using Apollo in your project you can try the Apollo GraphQL Extension for VS Code

Use GraphQL schema to create TS types and react hooks

Very often when working with backend it is useful for frontend application to know what response can we get.

When working with TypeScript we can actually generate types and hooks using schema.graphql or even “live” backend.

This is where graphql-codegen comes in handy

When you need to create generic components for resources (types) shared across different components you can use typescript plugin

When writing graphql queries, you can also generate type-safe react hooks with typescript-react-apollo plugin. With this plugin you only need to write *.graphql with desired Query, Mutation, Subscription or Fragment (you don’t need to import fragments in your quries!) and respective hooks will be created.

Example configuration codegen.yaml file from project:

overwrite: true

schema: 'http://localhost:4000/graphql'

documents:
  - 'src/**/queries.ts'
  - 'src/**/*.graphql'

generates:
  src/__generated__/types.tsx:
    plugins:
      - 'typescript'
    config:
      maybeValue: T | undefined

  src/__generated__/operations.tsx:
    preset: import-types
    presetConfig:
      typesPath: ./types
    plugins:
      - typescript-operations
    config:
      maybeValue: T | undefined

  src/__generated__/hooks.tsx:
    preset: import-types
    presetConfig:
      typesPath: ./operations
    plugins:
      - typescript-react-apollo
    config:
      maybeValue: T | undefined

React app bundle optimalization

As with any performance improvements, it’s important to have the tooling to evaluate if any changes provide value.

Tooling

In case of React apps setup with CRA it is source-map-explorer non CRA users can use other tools like webpack-bundle-analyzer

browser devtools with network throttling Imgur

Step 1

Decide what’s the lowest network speed that need to work relatively fast. (I have picked fast 3G)

Step 2

Build the application as for production environment npm run build and then serve -s build -l 3002 in CRA or open the deployed app.

Step 3

Throttle the network and force load all resources without using cache CMD+Shift+R. If the application loads relatively fast, there might not be the need to split the code at all.

Step 4

Analyze generated bundle using source-map-explorer or webpack-bundle-analyzer (non CRA). Spot biggest/rarely used elements. In my case it was:

  • TinyMCE used in only one page
  • Lodash being included 3 times (lodash.js lodash.min.js lodash-es)
  • React-Player used only in a few pages
  • Translations (en and pl)
  • Constants contained some not needed data

Step 5

Tackle the biggest issues and evaluate the results (step 4)

  • Use React.lazy and Suspense to lazy load parts of the application
  • When doing manual webpack code splitting remember about defining shared dependencies
  • Check for babel transforms eg. babel-plugin-lodash
  • Some modules can be aliased lodash: 'lodash-es', so they are included only once.
  • Some packages offer optimization themselves eg. import ReactPlayer from 'react-player/lazy' lazy loading players for different video hostings.
  • Load translation files lazily using eg. i18next-xhr-backend

Details depend on every specific case.

Step 6

If tackling the biggest elements is not enough, continue splitting the app per route or group of routes accessible for different users. eg. split admin routes, regular user routes and not logged in guests routes.

Profit!

Unless your application is gigantic, following all steps should be enough. In my case handling initial issues found in step 4 was enough.

Tips for implementing RBAC in React

Implementing RBAC in React (Role-Based Access Control) means you will need to add logic in multiple components to check if user has the correct role to display part of the UI.

Here is how using HOC’s enables clean code.

step 1

The assumption is store user roles are stored in context or redux.

Create withRole HOC

export default const withRole = (roles) => (Component) => (props) => {
 const {userRoles} = useContext(userRoles)
 if (userRoles.match(roles)) {
  return <Component {props} />
 }
 return null
} 

step 2

This HOC can be easily applied on any component.

import Button from "./Button"
import Something from "./Something"

const RestrictedButton = withRole(['admin', 'manager'])(Button)
const RestrictedSomething = withRole(['editor'])(Something)

const SomeComponent = () => {
 return (
  <div>
    <RestrictedButton>Only admin and manager sees me</RestrictedButton>. 
    <RestrictedSomething someProp={someProp}/>
  </div>
)}

step 3

It’s useful to create helpers with already applied roles.

export const withAdminRole = withRole(['admin'])
export const withEditorRole = withRole(['editor'])
export const withManagmentRole = withRole(['admin', 'editor'])

and use them like that:

const RestrictedButton = withManagmentRole(Button)
const RestrictedSomething = withEditorRole(Something)

important

HOC’s should always be created outside of the components, to prevent them being recreated on every render.

const MyComponent = () => {
  // VERY BAD
  const EditorButton = withRole('editor')(Button)
  const AdminButton = withAdminRole(Button)
  return (
    <>
      <EditorButton />
      <AdminButton />
    </>
  )
}
// GOOD
const EditorButton = withRole('editor')(Button)
const AdminButton = withAdminRole(Button)
const MyComponent = () => {
  return (
    <>
      <EditorButton />
      <AdminButton />
    </>
  )
}

Configure graphql syntax highlight in IntelliJ IDE's

To enable syntax highlight in graphql query/mutation definition in IntelliJ IDE’s follow few steps.

Initially gql query is displayed as regular string. Imgur

Step 1

In editor preferences > plugins > marketplace find JS GraphQL plugin Imgur

Step 2

Then you need to configure .graphqlconfig by selecting: new > GraphQL Configuration File in project root file Imgur schemaPath property should point to schema.graphql file in your project

Step 3

If you configure the application correctly you should see the schema discovered and “No errors found” Imgur

End result

Now you should see syntax highlight, suggestions and validation based on graphql schema. Imgur

Additional info

If you have problems with the setup checkout the plugin documentation

Monitor Redux store on production

With redux devtools disabled on production it’s problematic but possible to monitor dispatched actions and state changes. Here’s how it can be done.

Step 1

You need to find this code in your Sources. imgur

Even if they are minified, you can search for text 'Reducers may not dispatch actions.' which is close to the code we are interested in. Here is how it look in my case. Imgur

Step 2

Now you only need to add logpoint(s) to display action and state. Imgur

Imgur STATE BEFORE

{
  actionType: e.action.type, 
  action: e.action, 
  stateBeforeAction: s.computedStates[s.computedStates.length - 1].state
}

STATE AFTER

{
  actionType: e.action.type,
  action: e.action, 
  stateAfterAction: s.computedStates[s.computedStates.length - 1].state
}

IMPORTANT

In your case the code might be minified differently so you might have different letters instead of “e” and “s”.

Now then you click through the app (or reload the page) you should see in the console the feed of actions and state. Imgur

Redux devtools config with redux-toolkit

When configuring redux store you have to manually enable devtools. Often they are only enabled in development environment.

Redux toolkit by default enables devtools on all environments. It is easy to overlook that and forget disabling devtools on production.

However some say having devtools enabled in production is not an issue.

  const store = configureStore({
    reducer: rootReducer,
    middleware: getDefaultMiddleware(),
    // do not forget this
    devTools: process.env.NODE_ENV !== 'production',
  })

Redux suggested store structure.

Redux itself is not opinionated about how we design the store structure, but having good structure allows us to write simpler, less bug prone code. Based on redux style guide, state normalization and own experiences I would like to suggest some data shape for single resource. Depending on the specific needs of the project the structure should be adjusted, but it should be sufficient for standard use-cases.

const resource = {
  // normalized data for resource
  byId: {
    id1: {id: "id1", ...rest_of_item1_data},
    id2: {id: "id2", ...rest_of_item2_data},
  },

  // default list of items (key 'list' is just example)
  list: {
    // ids of users in the list
    // ids could be sorted, filtered
    // so there is no need to calculate them in selectors
    ids: ["userId1", "userId2"],
    // status of list operation
    // can be idle, loading, loaded, updating, etc.
    status: 'idle',
    // error data for the whole list operations (when appears)
    error: false,
    // metadata for the whole list
    // loadedAt and state are just example properties
    meta: {
      loadedAt: 7305798374957,
      stale: false,
    }
  },

  // when there is a need to manage another list
  someOtherList: {
    ids: ["userId4", "userId5"],
    status: 'loading',
    error: false,
    meta: {}
  },

  // default singular resource (key 'single' is just example)
  // for CRUD operations on single resource
  single: {
    id: 'id1',
    status: 'idle',
    error: false,
    meta: {}
  },

  // when there is a need to manage another singular resource
  anotherSingle: {
    id: 'id1',
    status: 'idle',
    error: false,
    meta: {}
  }
}

Use debugger in jest tests

Normally debugger does not stop test execution and allow us to check the application when running jest tests. However we can do it by passing --inspect flag to node and using chrome devtools for node.

Step 1

When using CRA add to your package.json scripts:

"test:debug": "react-scripts --inspect test --runInBand --no-cache",

When not using CRA add to your package.json scripts:

"test:debug": node --inspect node_modules/.bin/jest --runInBand

Step 2

In Chrome open chrome://inspect and click Open dedicated DevTools for Node you should see new inspector window open. (do not close it)

Step 3

Add debugger keyword in the tested code/component.

Step 4

Run npm run test:debug

And there it is. In a moment in the open inspector window, you should see test executions stopped at your breakpoint.


You could also use debugger in terminal or your IDE. More info in the article and node docs

React Redux code-smells: Storing props in state

With only a few exceptions storing props in state is anti-pattern, because:

  • storing the same/similar data is not optimal usage of memory
  • keeping two sources of data in sync is brittle and bug prone
  • often there is a cleaner way of implement the feature

bad case: keeping transformed data

export function MyComponent({ dateString }) {
  // DON'T
  const [timestamp, setTimestamp] = useState(() => new Date(dateString).getTime());

  return <div>Some UI do not mind me</div>;
}

if timestamp is not changed by MyComponent, it could be implemented simply by useMemo

export function MyComponent({ dateString }) {
  // DO
  const timestamp = useMemo(() => new Date(dateString).getTime(), [dateString])

  return <div>Some UI do not mind me</div>;
}

if timestamp is changed by MyComponent, maybe parent component should handle it

export function MyComponent({ timestamp, setTimestamp }) {
  return <div>Some UI do not mind me</div>;
}

That way we’ll not have duplication of data

good case: props provide only initial/defaultValue and we do not care if it is updated

If we receive defaults from parent, then they can be safely used by the children in state. That way we could also implement state reset.

export function MyComponent({ defaultTimestamp }) {
  // OK
  const [timestamp, setTimestamp] = useState(() => defaultTimestamp);
  const resetTimestamp = () => setTimestamp(defaultTimestamp)

  return <div>Some UI do not mind me</div>;
}

React Redux code-smells: Data preparation in component

If you have Redux in React project you should not handle data preparation in components. Why? Take a look on example below.

export function MyComponent({ userId, uniqueness }) {
  const user = useSelector((state) => getUser(state, userId));
  const selectedFilter = useSelector(getFilter);
  const selectedSorting = useSelector(getSorting);

  // in function components we can use useMemo for optimization
  // but in class components we would not be able to optimize this properly
  const answers = useMemo(() => {
    if (!user) return [];
    const uniqAnswers = uniqBy(user.answers, uniqueness);
    const filteredAnswers = filter(uniqAnswers, selectedFilter);
    return sortBy(filteredAnswers, selectedSorting);
  }, [user, selectedFilter, selectedSorting]);

  if (!user) return "Loading";

  return (
    <div>
      {user.name}
      {answers.map((answer) => (
        <div key={answer.id}>{answer.description}</div>
      ))}
    </div>
  );
}

If we ever need to display answers, we would need to copy-paste the logic, or extract it to the reusable hook which still would not be the perfect solution.

Wherever possible preparation of data should be handled by the selector. Even if the data comes from different reducers, or component state/props.

That way:

  • Code can be reused in other places
  • Component has less code
  • Reselect selectors have better performance by default
const getUserWithSortedAnswers = createSelector(
  getUser,
  getFilter,
  getSorting,
  (_, _2, uniqueness) => uniqueness,
  (user, selectedFilter, selectedSorting, uniqueness) => {
    if (!user) return [];
    const uniqAnswers = uniqBy(user.answers, uniqueness);
    const filteredAnswers = filter(uniqAnswers, selectedFilter);
    const sortedAnswers = sortBy(filteredAnswers, selectedSorting);

    // in this example sorted answers are modified in user object
    // but this can be done as separate selector eg. getSortedAnswers
    return { ...user, answers: sortedAnswers };
  }
);

export function MyComponent({ userId, uniqueness }) {
  // selector can receive component data from state or props (uniqueness)
  const user = useSelector((state) => 
     getUserWithSortedAnswers(state, userId, uniqueness)
  );

  if (!user) return "Loading";

  return (
    <div>
      {user.name}
      {user.answers.map((answer) => (
        <div key={answer.id}>{answer.description}</div>
      ))}
    </div>
  );
}

If you do not have redux in your React project you can do data preparation in reusable hooks or in wrapper components. As it also provides some reusability and decreases component size.

React code-smells: Passing unnecessary props

Component receiving many props might suggest something is wrong.

In this case MyComponent receives many props used only to calculate another values.

function MyComponent({ value, format, isVisible, color, height, width }) {
  const displayValue = useMemo(() => {
    if (!isVisible) return "";
    if (!value) return "";

    value.transform(format);
  }, [isVisible, value, format]);

  return (
    <div style={{ color, height, width }}>Some content and {displayValue}</div>
  );
}

function MyParentComponent() {
  // value, format, isVisible, color, height, width come from state or somewhere else

  return (
    <div>
      <h2>Here will be my component</h2>
      <MyComponent
        value={value}
        format={format}
        isVisible={isVisible}
        color={color}
        height={height}
        width={width}
      />
    </div>
  );
}

In such cases we could simplify the component by calculating the values in parent or additional wrapper component and pass only that.

function MyComponent({ style, displayValue }) {
  return <div style={style}>Some content and {displayValue}</div>;
}

function MyParentComponent() {
  // value, format, isVisible, color, height, width come from state or somewhere else

  const style = useMemo(
    () => ({ color, height, width }), 
    [color, height, width]
  );

  const displayValue = useMemo(() => {
    if (!isVisible) return "";
    if (!value) return "";

    value.transform(format);
  }, [isVisible, value, format]);

  return (
    <div>
      Here will be my component
      <MyComponent style={style} displayValue={displayValue} />
    </div>
  );
}

React code-smells: Big form components

Big components suggest that there might be too much going on inside. However sometimes it is hard to remove/extract the logic, as it really belongs there. That’s the case often with form components. In such cases we can extract related groups of logic into hooks.

function QuestionForm({ defaultQuestion }) {
  const [questionData, setQuestionData] = useState(defaultQuestion);

  // ====== stuff related to image refresh ======

  const [imageTimer, setImageTimer] = useState({});

  useEffect(
    function refreshFrontendSignedImages() {
      // logic for refreshing
    },
    []
  );

  useEffect(function setupRefreshForInitialImages() {
    // logic to refresh setup
  }, []);

  // ====== stuff related to submitting ======

  const dispatch = useDispatch();

  const [questionValidationErrors, setQuestionValidationErrors] = useState([]);

  const cleanupSaveActions = useCallback(() => {
    // cleanup handler logic
  }, []);

  const onSubmit = useCallback(() => {
    // submit handler logic
  }, []);

  // ====== stuff related to handling changes ======

  const handleTitleChange = useCallback(({ target }) => {
    //  handle title change
  }, []);

  const handleChoicesUpdate = useCallback((choice, index) => {
    // handle choices update
  }, []);

  const handleTopicsUpdate = useCallback((topicIds) => {
    // handle topic update
  }, []);

  return <form>Some Form UI</form>;
}

After extracting imageRefresh, submitHandlers and changeHandlers logic to hooks we have certain benefits:

  • more readable component without dozens of functions flying around
  • functions are grouped by their utility, so it’s easier to reason about them as we don’t have submit functions surrounded by change handlers
  • whenever you need to work on part of the functionality (like image refresh) you have all functions in one place
  • hooks can be reused (but this is not the main point of this refactoring)
function QuestionForm({ defaultQuestion }) {
  const [questionData, setQuestionData] = useState(defaultQuestion);

  const { setImageTimer } = useSignedImagesRefresh({
    setQuestionData,
    defaultQuestion,
  });

  const {
    onSubmit,
    onSubmitAndCreateAnother,
    validationErrors,
  } = useQuestionFormSubmitHandlers({ questionData });

  const {
    handleTitleChange,
    handleChoicesUpdate,
    handleTopicsUpdate,
  } = useQuestionFormChangeHandlers({ setQuestionData });

  return <form>Some Form UI</form>;
}

React code-smells: Mapping UI having methods for items

Whenever mapped elements have their own functions, they should be extracted to their own components.

const UsersList = () => {
  const [users, setUsers] = useState([])
  const fetchUsers = () => { ...fetchingLogic }

  const getHeader = (item, index) =>
    item.isAdmin 
      ? `${index + 100} :: ${item.superName} :: ${item.rank}` 
      : `${index} :: ${item.name} :: ${item.age}`

  const getImage = (item) =>
   item.url ? `${item.url}?token=${item.authToken}` : 'http://default.img.com'

  return (
    <div>
      {list.map((user, index) => (
        <div key={user.id}>
          <h3>{getHeader(user, index)}</h3>
          <p>Some introduction</p>
          {getImage(user)}
        </div>
      ))}
    </div>
  )
}

That way:

  • Item methods (getImage & getHeader) do not pollute UsersList component having own methods (fetchUsers)
  • There is no need to pass params to item methods
const User = ({ user, index }) => {
    const getHeader = () =>
      user.isAdmin
        ? `${index + 100} :: ${item.superName} :: ${item.rank}`
        : `${index} :: ${user.name} :: ${user.age}`
  
    const getImage = () =>
      user.url ? `${user.url}?token=${user.authToken}` : 'http://default.img.com'
  
    return (
      <div>
        <h3>{getHeader()}</h3>
        <p>Some introduction</p>
        {getImage()}
      </div>
    )
  }
  
  const UsersList = ({ list }) => {
    const [users, setUsers] = useState([])
    const fetchUsers = () => { ...fetchingLogic }

    return (
      <div>
        {users.map((user, index) =>
          <User user={user} index={index} key={user.id}/>
        }
      </div>
    )
  }

Styled-components pleasant class names

Styled-components generate unique hashes for each styled-component you create. They look like .nNUbag or .JbCpiZ. From a production perspective, these names are beneficial, since it reduces bundle size, but the development process is a nightmare.

Thankfully, there is a solution: babel-plugin-styled-components. It changes the class names to use the component name, which will help you in debugging process. The exact pattern is fileName__componentName-hash, eg. styles__StyledSearchBar-hXxaWb. Also, you don’t have to worry about production bundle size, cause it works only in development.

If you use create-react-app, the plugin is already set up. The only thing you have to do is update your imports.

import styled from 'styled-components/macro';

React Optimization of lists in big components

Big or often rerendering component which displays list of elements, can be optimized by extracting the list to separate component and using React.memo.

In example below it provided 40x speed improvement. YMMV of course.

In the examples I have provided different stages and mistakes this optimization. They also help understand why are useMemo and useCallback hooks useful.

react optimalization examples

Loading React & Redux dev tools in Cypress

Install webpack plugin: npm install --save-dev react-dev-tools-iframe-webpack-plugin

Update webpack config to enable the react dev tools iframe:

const ReactDevToolsIFramePlugin = require('react-dev-tools-iframe-webpack-plugin');

plugins: [
  // other plugins,
  new ReactDevToolsIFramePlugin(),
],

Update cypress plugins to load React & Redux dev tools for chrome. Add the paths to these extensions in a comma-separated string:

module.exports = (on, config) => {
  on('before:browser:launch', (browser = {}, args) => {
    if (browser.name === 'chrome') {
      args.push('--load-extension=/home/work/.config/google-chrome/Default/Extensions/lmhkpmbekcpmknklioeibfkpmmfibljd/2.17.0_0,/home/work/.config/google-chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.2.1_0');
      return args;
    }
    return null;
  });
};

Here’s a post where you can find out where the extensions are.

Use formik with context/hooks instead of render-props

Note that this feature is available in formik >= 2.0

Usually when you’re creating forms using formik you access formik props using render-prop pattern

export function MyForm() {
  return (
    <Formik
      initialValues={{ /* something here */ }}
      onSubmit={(values, actions) => {/* handler here */}}
    >
      {(formikProps) => (
        <form onSubmit={formikProps.handleSubmit}>
          <MyInputComponent value={formikProps.values.name} />
        </form>
      )}
    </Formik>
  )
}

Instead you can use formik as context provider (which it is under the hood actually) and use useFormikContext() hook or FormikConsumer component to consume provided form state.

Example below:

export function MyFormContainer() {
  return (
    <Formik
      {/* Under the hood Formik uses Context Provider */}
      initialValues={{ /* something here */}}
      onSubmit={(values, actions) => { /* handler here */ }}
    >
      {/* You do not have to use function here! */}
      {/* However you can, if you would like to :) */}
      <MyForm />
    </Formik>
  )
}

export function MyForm() {
  const { handleSubmit, values } = useFormikContext(); // formikProps

  return (
    <form onSubmit={handleSubmit}>
      <MyInputComponent value={values.name} />
    </form>
  );
}

This allows us to use formik props deep down in our nested components without drilling down formikProps.

Babel loader transpilation for Jest

Let’s imagine a following situation: we need to create a new npm package with create-react-app, in order to bundle some files in a package to have them available in a project (it’s possible to use create-component-lib for this task). The aforementioned sometimes requires from us to update our babel config.

In my latest task I had a situation where my babel config contained invalid (for a situation) presets:

module.exports =
{
  "presets": ["@babel/preset-env", ["react-app", { "absoluteRuntime": false }]]
}

In the above example, the build process creates a transpiled code, which contains babel runtime for minimalizing package size:

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/defineProperty"));

var _objectSpread4 = _interopRequireDefault(require("@babel/runtime/helpers/esm/objectSpread"));

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/classCallCheck"));

var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/createClass"));

var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/possibleConstructorReturn"));

var _getPrototypeOf3 = _interopRequireDefault(require("@babel/runtime/helpers/esm/getPrototypeOf"));

var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/inherits"));

Now when we start our test which uses a transpiled component it’s possible we receive error code like this:

Jest encountered an unexpected token

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation to specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    /Users/mobile32/projects/formik-generator/node_modules/@babel/runtime/helpers/esm/defineProperty.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){export default function _defineProperty(obj, key, value) {
                                                                                             ^^^^^^

    SyntaxError: Unexpected token export

      10 | exports.default = void 0;
      11 |
    > 12 | var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/defineProperty"));
         |                                               ^

      at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:403:17)
      at Object.require (dist/FormGenerator.js:12:47)

This happens because by default jest ignores transformations for everything in node_modules directory.

Now we have two possibilities to resolve this problem. In the first scenario we can add transformIgnorePatterns for our jest config to transpile babel runtime module:

transformIgnorePatterns: [
  '/node_modules/(?!@babel\/runtime)'
],

In the above example transpiled code still will be smaller in application runtime but it doesn’t crash our tests.

The second option is using another babel preset for proper transpilation:

module.exports = {
  plugins: [
    '@babel/plugin-proposal-class-properties',
  ],
  presets: [
    '@babel/preset-env',
    '@babel/preset-react',
  ],
}

Now after build, we get transpiled code working in a test environment, however, our code will be bloated with helpers required to mimic transpiled features (for example class inheritance):

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _react = _interopRequireWildcard(require("react"));

var _propTypes = _interopRequireDefault(require("prop-types"));

var _formik = require("formik");

var _yup = require("yup");

var _classnames = _interopRequireDefault(require("classnames"));

var _moment = _interopRequireDefault(require("moment"));

var _BooleanField = _interopRequireDefault(require("./FieldTypes/BooleanField"));

var _EnumField = _interopRequireDefault(require("./FieldTypes/EnumField"));

var _MoneyField = _interopRequireDefault(require("./FieldTypes/MoneyField"));

var _TextField = _interopRequireDefault(require("./FieldTypes/TextField"));

var _QuarterDateField = _interopRequireDefault(require("./FieldTypes/QuarterDateField"));

Reducing main bundle size with React lazy

On one of our projects we were able to reduce main bundle size from ~1080kB to ~820kB only by lazy loading one library (recharts).

in router file

import React, {Component, lazy, Suspense} from 'react'
//other imports

const StatisticsComponent = lazy(() => import('./path/to/component'))

export class Root extends Component {
  
  render(){
    return(
      <Router history={history}> 
        <Switch>
          // other routes
          <Suspense fallback={<div>Loading...</div>}>
            <Route exact component={StatisticsComponent} path='/statistics' />
          </Suspense>
        </Switch>
      </Router > 
      )
  }
}

ReactDatePicker Day off in Summer time issue

If you’re using react-datepicker, and the last time you’ve tested your date-picker was in winter time or sooner, please check if your date-picker still works properly.

Issue:

<DatePicker
  dateFormat="DD/MM/YYYY"
  onChange={val => this.setValue(input, val)}
  selected={input.value ? moment(input.value) : null}
  />

Seems pretty basic, right?

Date displayed:

React-date-picker displayed value

Real value:

Real value of date-picker

Solution:

Add

utcOffset={0}

to props in your react-date-picker.

<DatePicker
  dateFormat="DD/MM/YYYY"
  onChange={val => this.setValue(input, val)}
  selected={input.value ? moment(input.value) : null}
  utcOffset={0}
  />

You can read more about this issue Here.