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

await calls in code blocks #36

Open
MeepTech opened this issue Nov 4, 2022 · 6 comments
Open

await calls in code blocks #36

MeepTech opened this issue Nov 4, 2022 · 6 comments

Comments

@MeepTech
Copy link

MeepTech commented Nov 4, 2022

I have found useEffect as well as the await keyword cannot be used in the jsx: non-component blocks,

I'm trying to use an async function to load file data before passing it to a react component, if you know any workarounds I'd greatly appreciate it. Thanks!

Error:

 await is only valid in async functions and the top level bodies of modules
@OneComputerGuy
Copy link

I was testing this just today (I just discovered this plugin today) and the async/await works with useEffect, you need to set async on the effect function itself. The way I have it is like this:

const [data, setData] = useState({});

...

useEffect(async () => {
  const request = await fetch('url');
  const processedData = await request.json();
  setData(processedData.message)
}, []);

Not sure how you have your code. One thing to note is that I'm using the Component folder feature (I have a separate folder for all my React components and I call them somewhere else).

One thing to keep in mind and be aware when using async/await to perform fetch requests (specially to APIs) is that, when Obsidian detects a change when Live Preview is enabled (which is the default), it runs the formatter again on the entire note, which in return, triggers the React re-render cycle for the entire note, which runs the useEffect again.

If the note is being edited heavily, it will trigger an API request/useEffect render each time it detects a change, even if it's just one character. This could lead to API rate limits or performance hits if the file being loaded is large.

@MeepTech
Copy link
Author

Yea, thanks for the performance heads up, that's good to take into acount... though My issues lie with using the jsx: not jsx:component blocks sadly.

The jsx: blocks aren't turned into react components, so using useEffect doesn't make sense, as hooks must be used inside functional components.

@OneComputerGuy
Copy link

Don't know what's the usage that you currently have for components, but it doesn't seem to be the one indicated by the developer.

The current usage for the block/inline jsx which is defined by jsx: is to only work to call components, not define them.

If you want to define a component, you still need to define it on the component block (using the triple tick and using jsx:component:<ComponentName>) either in the same note or by creating a folder where you can store the components in separate files.

Trying to do something like the following code will never work or will take time to be supported (if the developer deems it necessary):

jsx: useEffect(()=>{}); return(<p>{state}</p>)

or

jsx: return(<p>This is a paragraph</p>)

One thing to keep in mind is the syntax to define component blocks, it has to follow the syntax jsx:component:<ComponentName> changing "<ComponentName>" for the name you want.

If you want, you can post the code block you're trying to create (sanitize any private information first before posting it here) and we can have a look

@MeepTech
Copy link
Author

MeepTech commented Dec 14, 2022

Don't know what's the usage that you currently have for components, but it doesn't seem to be the one indicated by the developer.

The current usage for the block/inline jsx which is defined by jsx: is to only work to call components, not define them.

If you want to define a component, you still need to define it on the component block (using the triple tick and using jsx:component:<ComponentName>) either in the same note or by creating a folder where you can store the components in separate files.

I'm not trying to define a component, I'm trying to use one with awaited data. I don't think i should need to make a different new component and then invoke it in a separate block every time I need to await anything. That would lead to multiple blocks required for each file just to re-use a component, which defeats the purpose of using react components imho.

Trying to do something like the following code will never work or will take time to be supported (if the developer deems it necessary):

jsx: useEffect(()=>{}); return(<p>{state}</p>)

Yes, I am aware you can't use useEffect outside of a component. I was pointing out how since jsx: is not a component that's not an option.

I want to do something like: (in a jsx: block, NOT a component block)

const data = await getData('Note.md');
<Component data={data}/>

And since a lot of internal obsidian data fetching functions are async, I can't avoid using await easily here.

@johtso
Copy link

johtso commented Mar 21, 2023

Just pass the path to the component and have the component do the fetching

@MeepTech
Copy link
Author

Just pass the path to the component and have the component do the fetching

Yea, this is probably my best option, though having to do that each time will be a bit annoying. I do wish we'd just be able to use await though haha.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants