Skip to content

Commit

Permalink
Fix useJson and <JsonEditor /> rule
Browse files Browse the repository at this point in the history
  • Loading branch information
sebelga committed Sep 1, 2020
1 parent e0d7039 commit 7e7611a
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import React, { useCallback } from 'react';
import React, { useCallback, useMemo } from 'react';
import { EuiFormRow, EuiCodeEditor } from '@elastic/eui';
import { debounce } from 'lodash';

Expand Down Expand Up @@ -52,9 +52,9 @@ export const JsonEditor = React.memo(
isControlled,
});

// https://github.com/elastic/kibana/issues/73971
/* eslint-disable-next-line react-hooks/exhaustive-deps */
const debouncedSetContent = useCallback(debounce(setContent, 300), [setContent]);
const debouncedSetContent = useMemo(() => {
return debounce(setContent, 300);
}, [setContent]);

// We let the consumer control the validation and the error message.
const error = isControlled ? propsError : internalError;
Expand All @@ -78,8 +78,7 @@ export const JsonEditor = React.memo(
debouncedSetContent(updated);
}
},
/* eslint-disable-next-line react-hooks/exhaustive-deps */
[isControlled]
[isControlled, onUpdate, debouncedSetContent]
);

return (
Expand Down
49 changes: 28 additions & 21 deletions src/plugins/es_ui_shared/public/components/json_editor/use_json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import { useEffect, useState, useRef } from 'react';
import { useEffect, useState, useRef, useCallback } from 'react';
import { i18n } from '@kbn/i18n';

import { isJSON } from '../../../static/validators/string';
Expand Down Expand Up @@ -45,11 +45,11 @@ export const useJson = <T extends object = { [key: string]: any }>({
onUpdate,
isControlled = false,
}: Parameters<T>) => {
const didMount = useRef(false);
const isMounted = useRef(false);
const [content, setContent] = useState<string>(stringifyJson(defaultValue));
const [error, setError] = useState<string | null>(null);

const validate = () => {
const validate = useCallback(() => {
// We allow empty string as it will be converted to "{}""
const isValid = content.trim() === '' ? true : isJSON(content);
if (!isValid) {
Expand All @@ -62,31 +62,38 @@ export const useJson = <T extends object = { [key: string]: any }>({
setError(null);
}
return isValid;
};
}, [content]);

const formatContent = () => {
const formatContent = useCallback(() => {
const isValid = validate();
const data = isValid && content.trim() !== '' ? JSON.parse(content) : {};
return data as T;
};
}, [validate, content]);

useEffect(() => {
if (didMount.current) {
const isValid = isControlled ? undefined : validate();
onUpdate({
data: {
raw: content,
format: formatContent,
},
validate,
isValid,
});
} else {
didMount.current = true;
if (!isMounted.current) {
return;
}
// https://github.com/elastic/kibana/issues/73971
/* eslint-disable-next-line react-hooks/exhaustive-deps */
}, [content]);

const isValid = isControlled ? undefined : validate();

onUpdate({
data: {
raw: content,
format: formatContent,
},
validate,
isValid,
});
}, [onUpdate, content, isControlled, formatContent, validate]);

useEffect(() => {
isMounted.current = true;

return () => {
isMounted.current = false;
};
}, []);

return {
content,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import React, { useState, useRef } from 'react';
import React, { useState, useRef, useCallback } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import {
Expand Down Expand Up @@ -134,9 +134,9 @@ export const LoadMappingsProvider = ({ onJson, children }: Props) => {
state.json !== undefined && state.errors !== undefined ? 'validationResult' : 'json';
const i18nTexts = getTexts(view, state.errors?.length);

const onJsonUpdate: OnJsonEditorUpdateHandler = (jsonUpdateData) => {
const onJsonUpdate: OnJsonEditorUpdateHandler = useCallback((jsonUpdateData) => {
jsonContent.current = jsonUpdateData;
};
}, []);

const openModal: OpenJsonModalFunc = () => {
setState({ isModalOpen: true });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import React, { FunctionComponent, useRef, useState } from 'react';
import React, { FunctionComponent, useRef, useState, useCallback } from 'react';
import { EuiConfirmModal, EuiOverlayMask, EuiSpacer, EuiText, EuiCallOut } from '@elastic/eui';

import { JsonEditor, OnJsonEditorUpdateHandler } from '../../../../../shared_imports';
Expand Down Expand Up @@ -66,10 +66,12 @@ export const ModalProvider: FunctionComponent<Props> = ({ onDone, children }) =>
raw: defaultValueRaw,
},
});
const onJsonUpdate: OnJsonEditorUpdateHandler = (jsonUpdateData) => {

const onJsonUpdate: OnJsonEditorUpdateHandler = useCallback((jsonUpdateData) => {
setIsValidJson(jsonUpdateData.validate());
jsonContent.current = jsonUpdateData;
};
}, []);

return (
<>
{children(() => setIsModalVisible(true))}
Expand Down

0 comments on commit 7e7611a

Please sign in to comment.