10play / 10tap-editor

React Native Rich Text Editor
MIT License
680 stars 26 forks source link

[BUG]: Editor isn't ready yet and setting content not working #175

Open mbpictures opened 3 months ago

mbpictures commented 3 months ago

Describe the bug I'm using the useEditorBridge() hook inside a modal component and on the mount of the component, I'm getting an "Editor isn't ready yet" warning.

To Reproduce This is my modal component:

export const TextEditorModal = ({
    isVisible,
    onClose,
    content
}: {
    isVisible: boolean,
    onClose: (text: string) => unknown,
    content?: string
}) => {
    const theme = useTheme();

    const editor = useEditorBridge({
        initialContent: content
    });

    useEffect(() => {
        if (!content || !isVisible) {
            return;
        }
        editor.setContent(content);
    }, [content, isVisible]);

    const handleClose = () => {
        editor.getHTML().then(onClose);
    }

    return (
        <Modal
            style={{
                backgroundColor: theme.colors.background,
                padding: 12,
                margin: 0,
                width,
                height
            }}
            isVisible={isVisible}
            onBackButtonPress={handleClose}
        >
            <CustomIconButton icon={"chevron-left"} onPress={handleClose} />
            <RichText editor={editor} />
            <KeyboardAvoidingView
                behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
                style={exampleStyles.keyboardAvoidingView}
            >
                <Toolbar editor={editor} />
            </KeyboardAvoidingView>
        </Modal>
    )
};

Expected behavior Content is updating once the useEffect hook triggers the setContent method. No warnings.

Screenshots

17Amir17 commented 3 months ago

Hey @mbpictures the issue here is that it takes some time for the editor to initialize and accept messages, that warning is thrown because a message was sent before the editor can do anything about it.

You can know the editor is ready from the editor state, try update your code to

    useEffect(() => {
        if (!content || !isVisible || !editor.getEditorState().isReady) {
            return;
        }
        editor.setContent(content);
    }, [content, isVisible]);

Of course this will not call setContent if it is not ready yet, but the initial content should be loaded from the prop anyways, alternatively you could list for isReady updates with useBridgeState

mbpictures commented 2 months ago

Thanks for this hint!

Even when I update my code like this, I'm getting the same warning:

    const editor = useEditorBridge({
        initialContent: content
    });
    const editorState = useBridgeState(editor);

    useEffect(() => {
        if (!content || !isVisible || !editorState.isReady) {
            return;
        }
        editor.setContent(content);
    }, [isVisible, editorState.isReady]);
jonhy751 commented 2 months ago

I also have this error

mbpictures commented 2 months ago

Update: even without setting the content at all I get the warning

17Amir17 commented 2 months ago

I'm unable to reproduce this, could you share a clean repo where this happens so I can investigate?

jonhy751 commented 2 months ago

I'm creating

jonhy751 commented 2 months ago

I managed to reproduce the error... this code returns the error:

`Editor isn't ready yet at Suspense at Freeze (http://10.0.2.2:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&lazy=true&minify=false&app=com.taptest&modulesOnly=false&runModule=true&transform.routerRoot=app&transform.engine=hermes&transform.bytecode=true:135073:23) at DelayedFreeze (http://10.0.2.2:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&lazy=true&minify=false&app=com.taptest&modulesOnly=false&runModule=true&transform.routerRoot=app&transform.engine=hermes&transform.bytecode=true:135019:22) at RNSScreenStack at ScreenStack (http://10.0.2.2:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&lazy=true&minify=false&app=com.taptest&modulesOnly=false&runModule=true&transform.routerRoot=app&transform.engine=hermes&transform.bytecode=true:135390:25) at NativeStackViewInner (http://10.0.2.2:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&lazy=true&minify=false&app=com.taptest&modulesOnly=false&runModule=true&transform.routerRoot=app&transform.engine=hermes&transform.bytecode=true:132508:22) at RCTView

code

I realized that when I do an if(test) return

17Amir17 commented 2 months ago

~~If this is only happening on new versions of expo, this might be caused from the isExpo util` not working https://github.com/10play/10tap-editor/blob/main/src/utils/misc.ts~~

EDIT: sorry this is not related, the best way to go forward would be to provide me with a repo that reproduces it

mbpictures commented 2 months ago

I'm using a bare react native project, with one expo-module integrated (expo-av)

jonhy751 commented 2 months ago

I realized that the editor needs an input to be rendered together. In my code, the editor was rendered first and after a few milliseconds my input was rendered on the screen, causing the error. I managed to solve it by setting the input to render right when the component started, together with the editor.

ryzencool commented 1 month ago

I realized that the editor needs an input to be rendered together. In my code, the editor was rendered first and after a few milliseconds my input was rendered on the screen, causing the error. I managed to solve it by setting the input to render right when the component started, together with the editor.

I have encountered the same issue. Could you please share your code? Thank you very much.