0

I have a component defined as Attack in a file named dice.js. In some instances I want a specific prop (m) to be filled out automatically

dice.js

...
export function Attack({ n, h, d, m = '' }) {
  return (
    <div>foob, {`${n} ${h} ${d} ${m}`}</div>
  );
}
...other components...

This component is then imported into into an mdx file for users to add to their posts:

post.mdx

blah blah blah <Attack n="foo" h="bar" d="foobar" /> // no 'm' prop

Great. Works perfectly. BUT!

There is a place where I want to add another prop that will always be filled in so that users don't have to type it out and I'm having trouble understanding why it doesn't work:

search.js

...imports...

// I don't want users to have to use a different tag so I imported it with a different name.
// Then I will rename it to the original name with the added prop.

import {Attack as SearchAttack} from './dice';

...

const Attack = React.cloneElement(
  SearchAttack(),
  { m: 'name' },
);

...

// A component that renders markdown from YAML front matter that users fill their content with. 
// This works when I don't attempt to add a prop and import the component with its normal name.

<MarkdownView components={ Attack } markdown={content} />

But the page always loads with an error: Error in function Attack in ../PATH/TO/COMPONENT/dice.js: Cannot read properties of undefined (reading 'n')

I don't know why this is occurring. I've checked the front matter and it is formatted like this:

post.mdx

...stuff...
<Attack n="foo" h="bar" d="foobar" />
...

I expect it to receive the new prop along with the previously defined props.

<div>foob, foo bar foobar name</div>

iamgarrett
  • 49
  • 1
  • 7

2 Answers2

0

You tried to clone a thing that is expected to be a react element. But what you supplied to it as a parameter is not a jsx (see SearchAttack() from the code block below).

const Attack = React.cloneElement(
  SearchAttack(), // THIS IS NOT RIGHT!
  { m: name },
);

You tried to run a component function as a function (and specified no arguments to it, btw). To create a valid jsx you should use createElement

Sergey P. aka azure
  • 3,993
  • 1
  • 29
  • 23
  • I've attempted replacing `SearchAttack()` with both `` and just `SearchAttack` - both give me an error: `Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.` This is why I tried running it as a function. – iamgarrett Apr 28 '22 at 16:18
  • Why don't you just define another component function like `const SearchAttack = (props) => { return }` Is that what you were trying to achieve? To have another component "class" to be able to produce instances of the existing component "class" with some prop predefined? – Sergey P. aka azure May 02 '22 at 12:19
0

I ended up not using React.cloneElement at all and instead used this amazing solution to adding props: https://stackoverflow.com/a/68946448/3609711

iamgarrett
  • 49
  • 1
  • 7