Wątek przeniesiony 2023-09-15 11:39 z JavaScript przez Riddle.

Jak nie generować zmiennej na nowo?

0

Mam pewna aplikacje w ktorej w jednym z komponentow mam nastepujacy kod:

useEffect(() => {
    if (!editor) return;
    let cmInstace;

    const codeView = (editor as Editor).extensionManager.extensions.find(
        (e) => e.name === "code_view"
    );

    if (codeView && !cmInstance) {
        const { codemirror, codemirrorOptions } = codeView.options;
        if (codemirror) {
            // merge options
            const cmOptions = {
                ...codemirrorOptions,
                readOnly: !(editor as Editor).isEditable,
            };
            cmInstance = codemirror.fromTextArea(cmTextAreaRef.current, cmOptions);
        }
    }

    if (isCodeViewMode) {
        cmInstance.setValue((editor as Editor).getHTML()); // init content
        // Format code
        cmInstance.execCommand("selectAll");
        const selectedRange = {
            from: cmInstance.getCursor(true),
            to: cmInstance.getCursor(false),
        };
        cmInstance.autoFormatRange(selectedRange.from, selectedRange.to);
        cmInstance.setCursor(0);
    } else {
        const content = cmInstance.getValue();
        (editor as Editor).commands.setContent(content, true);
        // Destroy code mirror
        const element = cmInstance.doc.cm.getWrapperElement();
        element && element.remove && element.remove();
        cmInstance = null;
    }
}, [isCodeViewMode]);

W tym miejscu zalezy mi na tym zeby zmienna cmInstance nie byla na nowo generowana przy kazdym kolejnym uzyciu useEffect. Czyli:

  1. Obecnie, useEffect jest wywolyany gdy zmienia sie wartosc state isCodeViewMode. Pierwsze wywolanie ma miejsce gdy ta wartosc jest true i w takim wypadku cmInstance jest tworzony nastepuajco: cmInstance = codemirror.fromTextArea(cmTextAreaRef.current, cmOptions);. Za drugim razem useEffect jest wykonywany gdy isCodeViewMode jest false i w takim wypadku:
    obecnie: cmInstance jest tworzony na nowo znowy uzywajac cmInstance = codemirror.fromTextArea(cmTextAreaRef.current, cmOptions);
    docelowo: chcialbym zeby cmInstance z poprzedniego wywolania bylo uzyte.

Czyli problem jest w tym ze na poczatku w kolko definiuje let cmInstace; wiec przy kazdym wykonaniu useEffect zawsze na nowo bedzie inicjalizowana ta zmienna i zastanawiam sie jak to zmienic zeby dzialalo tak jak opisalem wyzej.

Prosze o pomoc :)

2

Masz conajmniej dwa wyjścia:

  • Albo stwórz ten obiekt poza komponentem i przekaż go jako prop
  • Albo wsadź instancję w useState()
1

Można też skorzystać z useRef jeśli zmiana cmInstance ma nie powodować przeładowania komponentu

1 użytkowników online, w tym zalogowanych: 0, gości: 1