better-react-mathjax

repository·master·Indexed 41 days ago

https://github.com/fast-reflexes/better-react-mathjax

A React component library for integrating MathJax into applications, supporting LaTeX, AsciiMath, and MathML. It utilizes functional components and the hooks API to render math while minimizing flashes of non-typeset content. Version 3.0.3-beta provides support for MathJax versions 2, 3, and 4, offering a provider-consumer pattern via MathJaxContext and MathJax components.

Tokens
7.2K
Snippets
20
Records
33
Agent score
48%

What's inside better-react-mathjax

  1. Configure renderMode for MathJax

    master

    The renderMode property determines how MathJax handles typesetting:

    • post (Recommended): Use this in most scenarios.
    • pre: Use this when using dynamic updates and you need to prevent MathJax from typesetting all content after every render for performance reasons, or for other specific use cases where post is problematic.
  2. How MathJaxContext and MathJax work together

    master

    To use MathJax in your React application, you must follow a two-step pattern:

    1. Wrap your app in MathJaxContext: This component is responsible for downloading MathJax and providing it to all child components. You should only use one MathJaxContext in your entire application. By default, it imports MathJax from a CDN.
    2. Use MathJax components for math content: Place MathJax components at various levels of your component tree to render actual math. The content inside a MathJax component can range from a single string of math to a large subtree of the DOM.

    Note: Both components include the "use client" directive, making them client components in frameworks like Next.js.

    const App = () => {
       return (
           <MathJaxContext>
               {/* APP CONTENT */}
           </MathJaxContext>
       )
    }
    
    const Component = () => {
       return (
           <div>
               <MathJax>{ /* math content */ }</MathJax>
               <p>Text with <MathJax>{ /* math content */ }</MathJax></p>
           </div>
       )
    }
  3. How MathJaxContext and MathJax components work together

    master

    The library uses a provider-consumer pattern to manage MathJax:

    1. MathJaxContext: Acts as the provider. It downloads the MathJax library and provides the context to all descendant components.
    2. MathJax (and MathJaxBaseContext): These are the consumer components. They use the context provided by MathJaxContext to typeset their content.

    Typesetting Lifecycle:

    • By default, a MathJax component typesets its content once initially.
    • If the dynamic flag is set, it typesets every time a change is detected.
    • To prevent
    # Concept: Provider-Consumer Pattern
    <MathJaxContext>
      <MathJax> ... </MathJax>
    </MathJaxContext>
  4. Configure display vs inline math in MathJax

    master

    MathJax supports display math (takes up more space/different font) and inline math (integrated into text).

    • Latex and MathML: Use specific delimiters (for Latex) or tag attributes (for MathML) to control the math style.
    • AsciiMath: All math in the app uses the same style, which is set in the configuration. By default, it is display math. To change this, add asciimath: { displaystyle: false } to your input configuration.
    • The inline prop: The MathJax component has an inline prop. This controls whether the wrapper element added by the component is inline or block. It is not synonymous with the math typesetting mode itself.

    Exception: If the MathJax component's renderMode prop is set to "pre", the component becomes a single piece of math (provided via the text prop), and the inline property directly controls the math mode of the output.

  5. How MathJaxContext works in your application

    master
    The MathJaxContext is a stateful component that downloads MathJax. While you can use multiple instances, it is highly recommended to wrap your entire application in a single MathJaxContext and avoid using it anywhere else. This ensures MathJax is only downloaded once and provides a stable environment for the lifetime of your app.
  6. Prevent flashes of non-typeset content

    master

    A common challenge is preventing users from seeing raw math strings before MathJax has finished typesetting. Depending on your content type, use these strategies:

    For Static Content

    • hideUntilTypeset: Set this prop to 'first' on individual MathJax components or on the MathJaxContext to hide content until the initial typesetting is complete.
    • Coordinated Hiding: Use onInitTypeset on components or onStartUp/onLoad on the MathJaxContext to show entire page sections only after typesetting is finished.

    For Dynamic Content

    • dynamic={true}: Ensure this is set so that updates are re-typeset.
    • hideUntilTypeset='every': Set this to 'every' to hide content during every update. This may cause a short blink but prevents showing unformatted math.
    • renderMode='pre': This mode typesets the math before inserting it into the DOM. This is often the most effective way to eliminate flashes, though it may limit MathJax's ability to adapt to the surrounding context.
  7. Best practices for using MathJax components

    master

    To ensure correct typesetting and performance, follow these guidelines:

    • Avoid Nesting: Do not nest MathJax components. This causes the same math content to be typeset multiple times unnecessarily.
    • Handle Dynamic Content Carefully: When the dynamic property is set to true, avoid mixing math expressions with literal text within the same DOM element due to React/DOM manipulation conflicts.
      • Do: <p>{ "An example is the equation $${num}x^4 = 100$" }</p>
      • Do: <p>An example is the equation <span>{ "$${num}x^4 = 100$" }</p>
      • Don't: <p>An example is the equation ${num}x^4 = 100$</p>
      • Don't: <p>An example is the equation { "$${num}x^4 = 100$" }</p>
    • Manage Re-renders: Do not wrap content that re-renders on its own without the MathJax component also re-rendering. If a child re-renders but the parent MathJax component does not, the math will not be typeset anew. If you encounter this, wrap smaller portions of the math in their own MathJax components so that the state change triggers a re-render of the component containing the math.
    • Optimize Performance: If typesetting many small components is slow, group them. Replace many individual MathJax components with a single MathJax component wrapping a larger portion of the DOM sub-tree to reduce typesetting overhead.
  8. Migrate from v1 to v2

    master
    When migrating from version 1 to version 2, you must ensure that your application does not attempt to use MathJax version 2 and version 3 simultaneously. You should use only one version of MathJax per loaded page. Even if you unmount and remount a MathJaxContext, the version prop must remain consistent. If you are loading a completely new page context (not just a route change in a Single Page Application), the version can be determined anew.
  9. Manage MathJax callbacks and queues

    master

    MathJax 2 uses a Callback and Queue system to handle asynchronous operations and ensure that typesetting tasks do not conflict.

    • Callback: Used to schedule tasks. You can use Delay(time, callback) to postpone execution or Queue(...args) to add tasks to the internal processing queue.
    • Queue: Manables the execution of tasks. It tracks pending and running tasks and provides methods like Push(specs), Suspend(), and Resume() to control the flow of processing.
    • CallbackObject: Represents a scheduled task, allowing you to call .reset() to cancel it.