-
-
Notifications
You must be signed in to change notification settings - Fork 893
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
base: main
Are you sure you want to change the base?
Conversation
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.
worth noting that I tested this on the demo/playground here and it works well |
readme.md
Outdated
### `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]. |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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] |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
Initial checklist
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
orMarkdownHooks
fits their use case.Closes GH-680.
Closes GH-682.