onCreate / onMount / onInit extension

I use dynamic compartment to reconfigure the editor based on doc content.

What is the best way of designing extension, which runs once? The idea, that it reads state, performs a single transaction (or something else) and then never called again until the compartment is changed again to one, where it is a part of the extensions set.

Should I use StateField for that?

Thanks

1 Like

Could this action not be dispatched by the code that does the configuration, rather than by an extension? If it’s a state field, it shouldn’t perform side effects, so it probably can’t do anything useful in this context. A view plugin constructor could work, maybe.

Thank you for an idea!
Then, will it be the most natural way to put it as an additional effect, where the language configuration is updated?

const autoLanguage = EditorState.transactionExtender.of(tr => {
//..................
//..................
  console.log('switching... to '+docType.name);
  return {
      effects: [SOME_SIDEFFECT(), languageConf.reconfigure(docType.plugins)] 
               //   ^^^^^^^^
  }

Unless SOME_SIDEEFFECT() actually is a pure function that returns a state effect, you don’t want to put it in an effects array. Like all state-level functions, transaction extenders are expected to be pure functions.

2 Likes

I see. By the way, is it a bad practice to introduce another transaction from the transactionExtender? Or should I alter the transaction by mine using a normal transactionFilter and combine it with effect of reconfiguration

Thank you again

If you mean dispatch it as a side effect, yes, that’s definitely bad practice. Not all transactions that are computed will be dispatched. So if you make stuff happen from filters/extenders, they may fire for transactions that never end up happening in your editor.

2 Likes

I should probably rethink the architecture of my modules, however, for other readers I show my solution (it might be useful for someone).

As @marijn pointed out, one could try ViewPlugin

const initializationPlugin = ViewPlugin.fromClass(
  class {
    constructor(view) {
      const doc = view.state.doc.toString().trim();

      //This is my special condition: when a user typed a specific word in the cell, then
      //reconfigure an editor (outside this extension) and check if the rest of the content is empty

      if (doc === ".ex" || doc === ".excalidraw") {
        
        //If empty, insert a special symbol [] after (needed for other plugins)
        //(this is sort of autocomplete, but it does not ask user's permission)

        const change = {from: doc.length, insert: '\n\n[]'};

        //Now check if we are still in update stage
        const tryUpdate = () => {
          if (view.updateState != 0) {
            setTimeout(tryUpdate, 200);
            return;
          }

          view.dispatch({changes: change})
        }

        //After this line, @marijn will most likely 
        //never answer my questions again. ;/
        setTimeout(tryUpdate, 100);
      }
    }
  }
);
1 Like