andi23rosca / solid-markdown

Render Markdown as Solid components
MIT License
106 stars 10 forks source link

Reactivity not working. #7

Closed DasLixou closed 9 months ago

DasLixou commented 2 years ago

When i use

const [markdown, { mutate, refetch }] = createResource(...);
return <SolidMarkdown children={markdown()} />;

it doesnt work. it only works with

return <div>{!markdown.loading && <SolidMarkdown children={markdown()} />}</div>;

please fix this.

nathanoy commented 1 year ago

I have run into the same problem, thank you for the workaround!

DaliborTrampota commented 1 year ago

Any update on this?

endereyewxy commented 1 year ago

Same here.

lyonbot commented 1 year ago

it's 2023 now, still not fixed

DasLixou commented 1 year ago

I've not been using this library anymore but #10 might be fixing it. Maybe try out the fork

ryansolid commented 10 months ago

Any news on this issue? I know there are a few MD options for Solid but it has come to my attention this is the only one to process it at runtime .. like via component. So hoping to see this was planned to be addressed.

aryzing commented 10 months ago

Ran into the same issue, and ensured reactivity (ab)using the fact that components are "just functions",

<div>
  {Markdown({
    children: markdown(),
  })}
</div>
ailectra commented 10 months ago

As the SolidJS ecosystem keeps on growing, I decided yesterday to port my React app to SolidJS. My project extensively uses remarkjs, and this reactivity issue is a big problem for the conversion of my app. In my quest to find a solution, I created a function leveraging the updated rehype-react library, which now supports a plethora of frameworks including SolidJS.

Here's the function I developed:

import { unified, PluggableList } from "unified"
import remarkParse, { Options as RemarkParseOptions } from "remark-parse"
import remarkRehype, {Options as RemarkRehypeOptions} from "remark-rehype"
import rehypeReact, { Options as RehypeReactOptions } from "rehype-react"
import {Component, createEffect, createSignal, JSX} from "solid-js"

export type MarkdownProps = {
    children: string
    remarkParseOptions?: RemarkParseOptions
    remarkRehypeOptions?: RemarkRehypeOptions
    rehypeReactOptions: RehypeReactOptions
    rehypePlugins?: PluggableList
    remarkPlugins?: PluggableList
}

export const Markdown: Component<MarkdownProps> = (props: MarkdownProps) => {
    const [jsxContent, setJsxContent] = createSignal<JSX.Element | null>()

    const processor = unified()
        .use(remarkParse, props.remarkParseOptions)
        .use(props.remarkPlugins || [])
        .use(remarkRehype, props.remarkRehypeOptions)
        .use(props.rehypePlugins || [])
        .use(rehypeReact, props.rehypeReactOptions)

    const processMarkdown = (source: string) => {
        setJsxContent(processor.processSync(source).result)
    }

    createEffect(() => {
        processMarkdown(props.children)
    })

    return (
        <>
            {jsxContent()}
        </>
    )
}

How to Use:

In dev :

import * as dev from "solid-js/h/jsx-dev-runtime"

<Markdown
                children={markdown()}
                rehypeReactOptions={{Fragment: dev.Fragment, jsxDEV: dev.jsxDEV, development: true}} />

In production :

import * as prod from "solid-js/h/jsx-runtime"

<Markdown
                children={markdown()}
                rehypeReactOptions={{Fragment: prod.Fragment, jsx: prod.jsx, jsxs: prod.jsxs}} />

I didn't package this in a library because I'm still in the early stages of my SolidJS journey. Maybe someone more experienced can try to use this code as a base?

aryzing commented 10 months ago

@DasLixou 's approach won't work if the markdown() value changes while loading remains true since SolidMarkdown isn't re-mounted. Currently, to ensure re-rendering of the markdown content, SolidMarkdown must be re-mounted with each change to its children.

When called as a function rather than as used as a JSX component, it's return value is re-evaluated whenever any signal used to call it changes, ensuring the displayed markdown is reactive.

<div>
  {Markdown({
    children: markdown(),
  })}
</div>
andi23rosca commented 10 months ago

i've kind of forgotten about this library and the fact that I don't get GH notification emails didn't help 😓

i'll spend some time this weekend and address the reactivity issues the library is a 1:1 port of react-markdown so i think a couple of things i did work against solid reactivity, since i was more familiar with react at that time

andi23rosca commented 9 months ago

hey everyone, did a complete refactor of the library over the weekend and just published v2.0.0 on npm guaranteed reactivity working properly this time around

will try to get a demo up on github pages, but for now if you want to test the new version real quick, clone this repo and do

pnpm install
pnpm dev

you'll find a text box where you can test different markdown syntax quickly and see it being rendered on the right

image
andi23rosca commented 9 months ago

forgot to reference the issue in the PR: https://github.com/andi23rosca/solid-markdown/pull/25