Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for async plugins #890

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Add support for async plugins #890

wants to merge 2 commits into from

Conversation

wooorm
Copy link
Member

@wooorm wooorm commented Feb 14, 2025

Initial checklist

  • I read the support docs
  • I read the contributing guide
  • I agree to follow the code of conduct
  • I searched issues and discussions and couldn’t find anything or linked relevant results below
  • I made sure the docs are up to date
  • I included tests (or that’s not needed)

Description of changes

This commit adds 2 new components that support
turning markdown into react nodes,
asynchronously.
There are different ways to support async things in React. Component with hooks only run on the client.
Components yielding promises are not supported on the client. To support different scenarios and the different ways the future could develop,
these choices are made explicit to users.
Users can choose whether MarkdownAsync or MarkdownHooks fits their use case.

Closes GH-680.
Closes GH-682.

This commit adds 2 new components that support
turning markdown into react nodes,
asynchronously.
There are different ways to support async things in React.
Component with hooks only run on the client.
Components yielding promises are not supported on the client.
To support different scenarios and the different ways the future
could develop,
these choices are made explicit to users.
Users can choose whether `MarkdownAsync` or `MarkdownHooks` fits
their use case.

Closes GH-680.
Closes GH-682.
@github-actions github-actions bot added 👋 phase/new Post is being triaged automatically 🤞 phase/open Post is being triaged manually and removed 👋 phase/new Post is being triaged automatically labels Feb 14, 2025
@wooorm
Copy link
Member Author

wooorm commented Feb 14, 2025

worth noting that I tested this on the demo/playground here and it works well

readme.md Outdated
Comment on lines 214 to 220
### `MarkdownHooks`

Component to render markdown with support for async plugins through hooks.

Hooks run on the client.
For async support on the server,
see [`MarkdownAsync`][api-markdown-async].
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we expand on this a bit? Including that this uses useState, and so will not immediately render on initial page load?

* React element.
*/
export function MarkdownHooks(options) {
const processor = createProcessor(options)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The processor is only needed inside the useEffect. We can move it there as well. That means the processor isn’t created on every render and doesn’t need to be in the useEffect dependency array.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn’t Object.is used for the dependencies? And because Object.is({}, {}) // false, that would mean putting a created processor in dependencies would never be equal?

const file = createFile(options)
setPromise(processor.run(processor.parse(file), file))
},
[options.children]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dependency should specify all component local values needed to run the effect.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you want an array of every field in options?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that’s why processor is outside.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t know what you mean by “component local values” — can you use (pseudo)code to explain your ideas?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently processor needs to be in the dependency array, because it’s defined inside MarkdownHooks. That will trigger infinite rerenders.

The real fix is to move the creation of processor inside the useEffect. and add all values needed to create it to the dependency array.

Best would be to enable eslint-plugin-react-hooks.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you are suggesting to add every field on options into the dependency array?
The caveats describe to not put objects in dependencies: https://react.dev/reference/react/useEffect#caveats.

const tree = use(promise)

/* c8 ignore next -- hooks are client-only. */
return tree ? post(tree, options) : createElement(Fragment)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don’t have to return an empty fragment here. It’s sufficient to return undefined.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would make the types for only this function different from the other ones

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🤞 phase/open Post is being triaged manually
Development

Successfully merging this pull request may close these issues.

Some plugins require async run
3 participants