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

Passing complex content into a react component into an mdx document. #474

Closed
rchrdnsh opened this issue Mar 19, 2019 · 7 comments
Closed

Comments

@rchrdnsh
Copy link

Not sure where on the internet to ask this, so I figured I would start where it's trying to be done and see of anybody here has any ideas or resources to lead me towards. I'm desiring to make react components that can be used in mdx documents where I can feed them content like the following, which is sort of a simple YAML like syntax.

<PracticeSchedule>
  Week 1: 
    Day 1:
      Play all 12 notes, starting with the note C
    Day 2:
      Play all 12 notes, starting with the note G
    Day 3:
      Play all 12 notes, starting with the note D
    Day 4:
      Play all 12 notes, starting with the note A
    Day 5:
      Play all 12 notes, starting with the note E
    Day 6:
      Play all 12 notes, starting with the note B
    Day 7:
      Rest
  Week 2: 
    Day 1:
      Play all 12 notes, starting with the note F#/Gb
    Day 2:
      Play all 12 notes, starting with the note C#/Db
    Day 3:
      Play all 12 notes, starting with the note G#/Ab
    Day 4:
      Play all 12 notes, starting with the note D#/Eb
    Day 5:
      Play all 12notes, starting with the note A#/Bb
    Day 6:
      Play all 12 notes, starting with the note F
    Day 7:
      Rest
</PracticeSchedule>

The preceding would be the desired author experience for a react component I'm working on that is a practice schedule for piano. I originally made a version of this in vanilla HTML and CSS and I tried tables and lists then but they didn't quite work for me in the styling department for various reasons, so I ended up making a series of divs with custom styling that ended up doing the job, but was all hand coded. So I desire to turn all that mess into a react component and feed it data in the preceeding manner, or something similar, that is keeping with the spirit of Markdown/YAML/MDX. I suppose I could feed the components props of arrays and objects filled with strings, but I would like to be able to keep the simple YAML/Markdown feel, even inside an instance of a react component. Does anybody know if something like this is even possible to do, and if so, would it be too much time/effort/trouble to implement?

@johno
Copy link
Member

johno commented Mar 19, 2019

This isn't very easy to achieve right now since MDX doesn't support embedding MD syntax inside JSX blocks. However, you can achieve something similar by breaking out the PracticeSchedule content into its own file:

index.mdx

import Content from './some-content.mdx'

# Hello, world!

<Content />

some-content.mdx

import styled from 'styled-components'

export default styled.div`
  & ul {
    color: tomato;
  }
  & ul ul {
    color: rebeccapurple;
  }
`

- Item one
  - Item one a
  - Item one b
- Item two
  - Item two a
  - Item two b

Then, in some-content.mdx you could import PracticeSchedule and export it as the default.

You could also manipulate the children passed to PracticeSchedule since it will just be a string, but the newline information for your syntax will be lost because JSX, similarly to HTML (or at least most tags/elements), isn't whitespace sensitive.

@ChristopherBiscardi
Copy link
Member

if you go the child manipulation route, you could also use something likejsYaml in the react component itself to parse children from a string. It'd require the `` syntax for strings though.

<PracticeSchedule>{`
Week 1: 
  Day 1:
}`</PracticeSchedule>

@rchrdnsh
Copy link
Author

rchrdnsh commented Mar 19, 2019

jsYaml looks interesting...gonna try and get a basic version of the component working first, then will circle back around to this if it seems worth trying...thank you both! 😁

@rchrdnsh
Copy link
Author

So here is how I am structuring my nested lists of content:

<PracticeSchedule 
  schedule = {
    {
      Week1: {
        Day1: {
          Day: `Day 1`,
          Tasks: [`1`, `2`, `3`]
        },
        Day2: {
          Day: `Day 2`,
          Tasks: [`4`, `5`, `6`]
        },
        Day3: {
          Day: `Day 3`,
          Tasks: [`7`, `8`, `9`]
        }
      },
      Week2: {
        Day1: {
          Day: `Day 1`,
          Tasks: [`Uno`, `Does`, `Tres`]
        },
        Day2: {
          Day: `Day 2`,
          Tasks: [`Quatro`, `Cinco`, `Seis`]
        },
        Day3: {
          Day: `Day 3`,
          Tasks: [`Siete`, `Ocho`, `Nueve`]
        }
      },
    }
  }
/>

...and it logs fine in the console, but then I get this error message from react:

Objects are not valid as a React child (found: object with keys {Week1, Week2}). If you meant to render a collection of children, use an array instead.
    in h1 (created by PracticeSchedule)
    in PracticeSchedule (created by Component)
    in div (created by MDXTag)
    in MDXTag (created by Context.Consumer)
    in Component (created by Component)
    in Component (created by Component)
    in Component (created by Context.Consumer)
    in Component (created by Context.Consumer)
    in Component (created by _default)
    in div (created by Context.Consumer)
    in StyledComponent (created by article__Content)
    in article__Content (created by _default)
    in div (created by Context.Consumer)
    in StyledComponent (created by article__Article)
    in article__Article (created by _default)
    in MDXProvider (created by _default)
    in _default (created by HotExported_default)
    in AppContainer (created by HotExported_default)
    in HotExported_default (created by PageRenderer)
    in main (created by Context.Consumer)
    in StyledComponent (created by Main___default)
    in Main___default (created by Context.Consumer)
    in div (created by Context.Consumer)
    in StyledComponent (created by App___default)
    in App___default (created by Context.Consumer)
    in div (created by Div100vh)
    in Div100vh (created by Context.Consumer)
    in StaticQuery (created by Layout)
    in Layout (created by PageRenderer)
    in PageRenderer (created by JSONStore)
    in JSONStore (created by EnsureResources)
    in ScrollContext (created by EnsureResources)
    in RouteUpdates (created by EnsureResources)
    in EnsureResources (created by RouteHandler)
    in RouteHandler (created by Root)
    in div (created by FocusHandlerImpl)
    in FocusHandlerImpl (created by Context.Consumer)
    in FocusHandler (created by RouterImpl)
    in RouterImpl (created by LocationProvider)
    in LocationProvider (created by Context.Consumer)
    in Location (created by Context.Consumer)
    in Router (created by Root)
    in Root
    in MDXScopeProvider
    in _default

with a code highlight:

(anonymous function)
/Users/rchrdnsh/Dropbox/Code/Gatsby/rykr-app/.cache/app.js:56
  53 | const preferDefault = m => (m && m.default) || m
  54 | let Root = preferDefault(require(`./root`))
  55 | domReady(() => {
> 56 |   renderer(<Root />, rootElement, () => {
  57 |     postInitialRenderWork()
  58 |     apiRunner(`onInitialClientRender`)
  59 |   })

sooo, not sure what to do...should I just wrap the whole thing in an array? How would I do that? Not sure how that would work, to be honest. Could I simplify my data model as well? Would that be a wise idea...ano how I really do want to get markdown/yaml up in these react components XD

@johno
Copy link
Member

johno commented Mar 27, 2019

Can you create a CodeSandbox with a reproduction? Sounds like your passing the object directly as children in PracticeSchedule.

@rchrdnsh
Copy link
Author

rchrdnsh commented Mar 27, 2019

This is all I'm doing in the component thus far...

import React from 'react'

const PracticeSchedule = (props) => {
  console.log(props.schedule)
  return (
      <h1>{props.schedule}</h1>
  )
}

export default PracticeSchedule;

trying to figure out how to make a code sandbox as well...

@rchrdnsh
Copy link
Author

rchrdnsh commented Mar 27, 2019

https://codesandbox.io/s/github/rchrdnsh/rykr

...will need to open up the render in a new window, cuz mobile styles aren't there yet, tho...

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

No branches or pull requests

3 participants