0

I would render a component as a Label content instead of a string.

Actually I'm getting this error:

The shorthand prop for "Box" component was passed a JSX element but this slot only supports string|number|object|array|ReactElements.

import AudioItem from '../containers/Media'
const AudioLabel = (props) => {
    let url = "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3"
    const [audio] = useState(new Audio(url));
    const [isPaused, setIsPaused] = useState(audio.paused)
    return (<Label content={({ ...props }) => (<><span>{props.content}</span> <AudioItem isPaused={isPaused} setIsPaused={setIsPaused} audio={audio} /></>)}
        circular
        image={{
            src: 'public/images/avatar/small/matt.jpg',
            avatar: true,
        }}
        icon={
            <CloseIcon
            />}
    />)
}
export default AudioLabel

Called component as prop.

import { Button, Header, List, RadioGroup, ItemLayout } from '@fluentui/react-northstar'
import { PlayIcon, PauseThickIcon } from '@fluentui/react-icons-northstar'

const AudioItem = (props) => {
    return (
        <ItemLayout
            headerMedia={<Button icon={props.isPaused ? (<PlayIcon />) : (<PauseThickIcon />)} onClick={() => { props.isPaused ? props.audio.play() : props.audio.pause(); props.setIsPaused(props.audio.paused) }} text content={props.isPaused ? "Play" : "Pause"} />}
        />
    )
}

How can I pass a component (with props) as content?

Issue reproduction

infodev
  • 4,673
  • 17
  • 65
  • 138

3 Answers3

1

I've checked the documentation of fluent. What you are trying to achieve is called render props in react. But fluent library named this as Shorthand Props

According to their doc you need to follow a specific pattern to achieve this. Here i've added the code for the Label Component and it removes the error. sandbox_link

<Label
      content={{
        chidren: ({ ...props }) => (
        <>
          <span>{props.content}</span>
            <AudioItem
              isPaused={isPaused}
              setIsPaused={setIsPaused}
              audio={audio}
            />
        </>)
      }}
      circular 
      image={{
        src: "public/images/avatar/small/matt.jpg",
        avatar: true
      }}
      icon={<CloseIcon />}
    />

Sifat Haque
  • 5,357
  • 1
  • 16
  • 23
  • Thanks , that's what I havn't get since I started using this lib . so I should specify `children` item When I want to render a react component. Thanks for the help – infodev Nov 26 '20 at 19:46
0

An arbitrary function is not a functional component. If you want React to compile a function as a component, you need (a) an identifier in scope and (b) a capital letter as first letter of this identifier. doc.

To make your code work, you need to create a new component that will render your span and your AudioItem.

Working example here: code

P.E. Joëssel
  • 1,393
  • 10
  • 18
  • OK So should put code inside a unique component, can you explain me why the code does not work if I use a functional component inside `content` – infodev Nov 26 '20 at 18:31
  • That may be odd but you did not send a functional component, just a function. To be compile as a component, you need (a) an identifier in scope and (b) a capital letter as first letter of this identifier. Otherwise, React will not compile your function to React.createElement(). https://reactjs.org/docs/jsx-in-depth.html#user-defined-components-must-be-capitalized. – P.E. Joëssel Nov 26 '20 at 18:52
0

I'd say that it's not the best idea to pass JSX as props, but if you're certain that's what you want, you can always convert it to string, then pass it, then convert it back again; like so (simple example):

const JSXToPass = () => {
    return (
        <div> example </div>
    );
}

const Parent = () => {
    return (
        <Child content={React.renderToString(JSXToPass)} />
    );
}

const Child = (props) => {
    return (
        <div dangerouslySetInnerHTML={{__html: props.content}} />
    );
}
k-wasilewski
  • 3,943
  • 4
  • 12
  • 29