Skip to content

Commit

Permalink
use arrow functions where possible (#1762)
Browse files Browse the repository at this point in the history
  • Loading branch information
VIKTORVAV99 authored Jul 15, 2024
1 parent 5c3c3eb commit 46e8ea5
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 82 deletions.
44 changes: 21 additions & 23 deletions src/TransWithoutContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,34 @@ import { warn, warnOnce } from './utils.js';
import { getDefaults } from './defaults.js';
import { getI18n } from './i18nInstance.js';

function hasChildren(node, checkLength) {
const hasChildren = (node, checkLength) => {
if (!node) return false;
const base = node.props ? node.props.children : node.children;
if (checkLength) return base.length > 0;
return !!base;
}
};

function getChildren(node) {
const getChildren = (node) => {
if (!node) return [];
const children = node.props ? node.props.children : node.children;
return node.props && node.props.i18nIsDynamicList ? getAsArray(children) : children;
}
};

function hasValidReactChildren(children) {
const hasValidReactChildren = (children) => {
if (Object.prototype.toString.call(children) !== '[object Array]') return false;
return children.every((child) => isValidElement(child));
}
};

function getAsArray(data) {
return Array.isArray(data) ? data : [data];
}
const getAsArray = (data) => (Array.isArray(data) ? data : [data]);

function mergeProps(source, target) {
const mergeProps = (source, target) => {
const newTarget = { ...target };
// overwrite source.props when target.props already set
newTarget.props = Object.assign(source.props, target.props);
return newTarget;
}
};

export function nodesToString(children, i18nOptions) {
export const nodesToString = (children, i18nOptions) => {
if (!children) return '';
let stringNode = '';

Expand Down Expand Up @@ -103,9 +101,9 @@ export function nodesToString(children, i18nOptions) {
});

return stringNode;
}
};

function renderNodes(children, targetString, i18n, i18nOptions, combinedTOpts, shouldUnescape) {
const renderNodes = (children, targetString, i18n, i18nOptions, combinedTOpts, shouldUnescape) => {
if (targetString === '') return [];

// check if contains tags we need to replace from html string to react nodes
Expand All @@ -119,15 +117,15 @@ function renderNodes(children, targetString, i18n, i18nOptions, combinedTOpts, s
// v2 -> interpolates upfront no need for "some <0>{{var}}</0>"" -> will be just "some {{var}}" in translation file
const data = {};

function getData(childs) {
const getData = (childs) => {
const childrenArray = getAsArray(childs);

childrenArray.forEach((child) => {
if (typeof child === 'string') return;
if (hasChildren(child)) getData(getChildren(child));
else if (typeof child === 'object' && !isValidElement(child)) Object.assign(data, child);
});
}
};

getData(children);

Expand All @@ -136,7 +134,7 @@ function renderNodes(children, targetString, i18n, i18nOptions, combinedTOpts, s
const ast = HTML.parse(`<0>${targetString}</0>`);
const opts = { ...data, ...combinedTOpts };

function renderInner(child, node, rootReactNode) {
const renderInner = (child, node, rootReactNode) => {
const childs = getChildren(child);
const mappedChildren = mapAST(childs, node.children, rootReactNode);
// `mappedChildren` will always be empty if using the `i18nIsDynamicList` prop,
Expand All @@ -145,9 +143,9 @@ function renderNodes(children, targetString, i18n, i18nOptions, combinedTOpts, s
(child.props && child.props.i18nIsDynamicList)
? childs
: mappedChildren;
}
};

function pushTranslatedJSX(child, inner, mem, i, isVoid) {
const pushTranslatedJSX = (child, inner, mem, i, isVoid) => {
if (child.dummy) {
child.children = inner; // needed on preact!
mem.push(cloneElement(child, { key: i }, isVoid ? undefined : inner));
Expand All @@ -169,12 +167,12 @@ function renderNodes(children, targetString, i18n, i18nOptions, combinedTOpts, s
}),
);
}
}
};

// reactNode (the jsx root element or child)
// astNode (the translation string as html ast)
// rootReactNode (the most outer jsx children array or trans components prop)
function mapAST(reactNode, astNode, rootReactNode) {
const mapAST = (reactNode, astNode, rootReactNode) => {
const reactNodes = getAsArray(reactNode);
const astNodes = getAsArray(astNode);

Expand Down Expand Up @@ -291,7 +289,7 @@ function renderNodes(children, targetString, i18n, i18nOptions, combinedTOpts, s
}
return mem;
}, []);
}
};

// call mapAST with having react nodes nested into additional node like
// we did for the string ast from translation
Expand All @@ -302,7 +300,7 @@ function renderNodes(children, targetString, i18n, i18nOptions, combinedTOpts, s
getAsArray(children || []),
);
return getChildren(result[0]);
}
};

export function Trans({
children,
Expand Down
28 changes: 12 additions & 16 deletions src/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,23 @@ export class ReportNamespaces {
});
}

getUsedNamespaces() {
return Object.keys(this.usedNamespaces);
}
getUsedNamespaces = () => Object.keys(this.usedNamespaces);

This comment has been minimized.

Copy link
@legend80s

legend80s Aug 6, 2024

Hi this commit is "use arrow functions where possible" but arrow function with class property is not common arrow function it depends on special babel plugin:
image
screenshot from https://www.freecodecamp.org/news/react-binding-patterns-5-approaches-for-handling-this-92c651b5af56/.

And it broke one of my project:

error  in ./node_modules/react-i18next/dist/es/context.js

Module parse failed: Unexpected token (16:20)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https:/
/webpack.js.org/concepts#loaders
|     });
|   }
>   getUsedNamespaces = () => Object.keys(this.usedNamespaces);
| }
| export const composeInitialProps = ForComponent => async ctx => {

 @ ./node_modules/react-i18next/dist/es/index.js 12:0-81 12:0-81 12:0-81 12:0-81
 ...

This comment has been minimized.

Copy link
@adrai

adrai Aug 7, 2024

Member

This comment has been minimized.

Copy link
@VIKTORVAV99

VIKTORVAV99 Aug 7, 2024

Author Contributor

Probably simplest to revert this line.

We have not run into any issues with but it seems like the safest approach. What do you think?

This comment has been minimized.

Copy link
@adrai

adrai Aug 7, 2024

Member

just reverted with v15.0.1

}

export function composeInitialProps(ForComponent) {
return async (ctx) => {
const componentsInitialProps = ForComponent.getInitialProps
? await ForComponent.getInitialProps(ctx)
: {};
export const composeInitialProps = (ForComponent) => async (ctx) => {
const componentsInitialProps = ForComponent.getInitialProps
? await ForComponent.getInitialProps(ctx)
: {};

const i18nInitialProps = getInitialProps();
const i18nInitialProps = getInitialProps();

return {
...componentsInitialProps,
...i18nInitialProps,
};
return {
...componentsInitialProps,
...i18nInitialProps,
};
}
};

export function getInitialProps() {
export const getInitialProps = () => {
const i18n = getI18n();
const namespaces = i18n.reportNamespaces ? i18n.reportNamespaces.getUsedNamespaces() : [];

Expand All @@ -55,4 +51,4 @@ export function getInitialProps() {
ret.initialLanguage = i18n.language;

return ret;
}
};
8 changes: 3 additions & 5 deletions src/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@ let defaultOptions = {
unescape,
};

export function setDefaults(options = {}) {
export const setDefaults = (options = {}) => {
defaultOptions = { ...defaultOptions, ...options };
}
};

export function getDefaults() {
return defaultOptions;
}
export const getDefaults = () => defaultOptions;
8 changes: 3 additions & 5 deletions src/i18nInstance.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
let i18nInstance;

export function setI18n(instance) {
export const setI18n = (instance) => {
i18nInstance = instance;
}
};

export function getI18n() {
return i18nInstance;
}
export const getI18n = () => i18nInstance;
4 changes: 2 additions & 2 deletions src/useSSR.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useContext } from 'react';
import { getI18n, I18nContext } from './context.js';

export function useSSR(initialI18nStore, initialLanguage, props = {}) {
export const useSSR = (initialI18nStore, initialLanguage, props = {}) => {
const { i18n: i18nFromProps } = props;
const { i18n: i18nFromContext } = useContext(I18nContext) || {};
const i18n = i18nFromProps || i18nFromContext || getI18n();
Expand Down Expand Up @@ -30,4 +30,4 @@ export function useSSR(initialI18nStore, initialLanguage, props = {}) {
i18n.changeLanguage(initialLanguage);
i18n.initializedLanguageOnce = true;
}
}
};
18 changes: 8 additions & 10 deletions src/useTranslation.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,18 @@ const usePrevious = (value, ignore) => {
return ref.current;
};

function alwaysNewT(i18n, language, namespace, keyPrefix) {
return i18n.getFixedT(language, namespace, keyPrefix);
}
const alwaysNewT = (i18n, language, namespace, keyPrefix) =>
i18n.getFixedT(language, namespace, keyPrefix);

function useMemoizedT(i18n, language, namespace, keyPrefix) {
return useCallback(alwaysNewT(i18n, language, namespace, keyPrefix), [
const useMemoizedT = (i18n, language, namespace, keyPrefix) =>
useCallback(alwaysNewT(i18n, language, namespace, keyPrefix), [
i18n,
language,
namespace,
keyPrefix,
]);
}

export function useTranslation(ns, props = {}) {
export const useTranslation = (ns, props = {}) => {
// assert we have the needed i18nInstance
const { i18n: i18nFromProps } = props;
const { i18n: i18nFromContext, defaultNS: defaultNSFromContext } = useContext(I18nContext) || {};
Expand Down Expand Up @@ -114,9 +112,9 @@ export function useTranslation(ns, props = {}) {
setT(getNewT);
}

function boundReset() {
const boundReset = () => {
if (isMounted.current) setT(getNewT);
}
};

// bind events to trigger change, like languageChanged
if (bindI18n && i18n) i18n.on(bindI18n, boundReset);
Expand Down Expand Up @@ -161,4 +159,4 @@ export function useTranslation(ns, props = {}) {
loadNamespaces(i18n, namespaces, () => resolve());
}
});
}
};
29 changes: 14 additions & 15 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Do not use arrow function here as it will break optimizations of arguments
export function warn(...args) {
if (console && console.warn) {
if (typeof args[0] === 'string') args[0] = `react-i18next:: ${args[0]}`;
Expand All @@ -6,6 +7,7 @@ export function warn(...args) {
}

const alreadyWarned = {};
// Do not use arrow function here as it will break optimizations of arguments
export function warnOnce(...args) {
if (typeof args[0] === 'string' && alreadyWarned[args[0]]) return;
if (typeof args[0] === 'string') alreadyWarned[args[0]] = new Date();
Expand Down Expand Up @@ -37,22 +39,22 @@ const loadedClb = (i18n, cb) => () => {
}
};

export function loadNamespaces(i18n, ns, cb) {
export const loadNamespaces = (i18n, ns, cb) => {
i18n.loadNamespaces(ns, loadedClb(i18n, cb));
}
};

// should work with I18NEXT >= v22.5.0
export function loadLanguages(i18n, lng, ns, cb) {
export const loadLanguages = (i18n, lng, ns, cb) => {
// eslint-disable-next-line no-param-reassign
if (typeof ns === 'string') ns = [ns];
ns.forEach((n) => {
if (i18n.options.ns.indexOf(n) < 0) i18n.options.ns.push(n);
});
i18n.loadLanguages(lng, loadedClb(i18n, cb));
}
};

// WAIT A LITTLE FOR I18NEXT BEING UPDATED IN THE WILD, before removing this old i18next version support
function oldI18nextHasLoadedNamespace(ns, i18n, options = {}) {
const oldI18nextHasLoadedNamespace = (ns, i18n, options = {}) => {
const lng = i18n.languages[0];
const fallbackLng = i18n.options ? i18n.options.fallbackLng : false;
const lastLng = i18n.languages[i18n.languages.length - 1];
Expand Down Expand Up @@ -91,9 +93,9 @@ function oldI18nextHasLoadedNamespace(ns, i18n, options = {}) {
if (loadNotPending(lng, ns) && (!fallbackLng || loadNotPending(lastLng, ns))) return true;

return false;
}
};

export function hasLoadedNamespace(ns, i18n, options = {}) {
export const hasLoadedNamespace = (ns, i18n, options = {}) => {
if (!i18n.languages || !i18n.languages.length) {
warnOnce('i18n.languages were undefined or empty', i18n.languages);
return true;
Expand All @@ -120,12 +122,9 @@ export function hasLoadedNamespace(ns, i18n, options = {}) {
return false;
},
});
}
};

export function getDisplayName(Component) {
return (
Component.displayName ||
Component.name ||
(typeof Component === 'string' && Component.length > 0 ? Component : 'Unknown')
);
}
export const getDisplayName = (Component) =>
Component.displayName ||
Component.name ||
(typeof Component === 'string' && Component.length > 0 ? Component : 'Unknown');
5 changes: 2 additions & 3 deletions src/withSSR.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { useSSR } from './useSSR.js';
import { composeInitialProps } from './context.js';
import { getDisplayName } from './utils.js';

export function withSSR() {
return function Extend(WrappedComponent) {
export const withSSR = () =>
function Extend(WrappedComponent) {
function I18nextWithSSR({ initialI18nStore, initialLanguage, ...rest }) {
useSSR(initialI18nStore, initialLanguage);

Expand All @@ -19,4 +19,3 @@ export function withSSR() {

return I18nextWithSSR;
};
}
5 changes: 2 additions & 3 deletions src/withTranslation.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { createElement, forwardRef as forwardRefReact } from 'react';
import { useTranslation } from './useTranslation.js';
import { getDisplayName } from './utils.js';

export function withTranslation(ns, options = {}) {
return function Extend(WrappedComponent) {
export const withTranslation = (ns, options = {}) =>
function Extend(WrappedComponent) {
function I18nextWithTranslation({ forwardedRef, ...rest }) {
const [t, i18n, ready] = useTranslation(ns, { ...rest, keyPrefix: options.keyPrefix });

Expand Down Expand Up @@ -33,4 +33,3 @@ export function withTranslation(ns, options = {}) {

return options.withRef ? forwardRefReact(forwardRef) : I18nextWithTranslation;
};
}

0 comments on commit 46e8ea5

Please sign in to comment.