1

For clean code & folder structure, I'm moving some data (in this case, modal data) to a separate file. However, I'm not able to put a component inside an object value. Here's what I want to do:

export function invalidId(id) {
   return {
      info: {
         title: "Invalid ID!",
         message: (
            <>
               The 
               <code className="inline-code">{id}</code>
               is invalid. Please make sure blah blah blah...
            </>
         ),
      },


      // I need help with this part
      buttons: {
         <>
            <Button label="Retry" />
            <Button label="More Info" >
         </>   
      }
   }
}
import { invalidId } form "modaldata";

setModalInfo(invalidId(id).info);
setModalButtons(invalidId(id).buttons);

I used return here because id is dynamic. The main problem is buttons part. What is the correct way to put JSX inside an object?

8
  • 1
    Can't you do it like you did with info.message? Using round instead of curly brackets? Commented Jan 7, 2022 at 15:29
  • Thanks! @ShamPooSham Wanna post it as an answer? I didn't notice I'm already using it... 😑 Commented Jan 7, 2022 at 15:37
  • @ShamPooSham - Oops, I'd just added that option to my answer and now I've seen your comment. (You don't need the (), you can just use the fragment directly, but people often do use () not least because they're used to doing it elsewhere because of the return semicolon problem.) If you post an answer, please @ ping me and I'll adjust mine to call attention to yours. Commented Jan 7, 2022 at 15:42
  • You don't even need brackets, just put the fragment tag (<>) on the same line as buttons: . T.J. Crowder did this in one of the solutions, so I won't post an answer. Commented Jan 7, 2022 at 15:43
  • 1
    @T.J.Crowder Thanks but it's alright, you can have it :) Your answer is perfect, giving many alternatives to people stumbling upon this question who might be looking for some other solution. Commented Jan 7, 2022 at 15:44

2 Answers 2

5

Remember that a JSX expression results in an object value (it gets converted into a call to React.createObject(/*...*/) or whatever else is set up as the JSX function). Like any other value, if you want to put that value inside an object, you either need to:

  1. Just use the fragment directly (not within another object); or

  2. Use a property name (or names); or

  3. Use an array

(Or make buttons a function that returns the fragment, as abhi patil shows.)

Here's #1 (note no {}):

buttons: <>
   retry: <Button label="Retry" />
   moreInfo: <Button label="More Info" >
</>

Here's #2, assuming you want separate property names for the two buttons:

buttons: {
   retry: <Button label="Retry" />,
   moreInfo: <Button label="More Info" >,
}

Here's #3, an array (rather than plain object) containing the two buttons:

buttons: [
   <Button label="Retry" />,
   <Button label="More Info" >,
]
Sign up to request clarification or add additional context in comments.

Comments

1

You need to return the jsx template in a object field and call it like a function.

export function invalidId(id) {
   return {
      info: {
         title: "Invalid ID!",
         message: ()=> (
            <>
               The 
               <code className="inline-code">{id}</code>
               is invalid. Please make sure blah blah blah...
            </>
         ),
      },


      // I need help with this part
      buttons:()=> (
         <>
            <Button label="Retry" />
            <Button label="More Info" >
         </>   
      )
   }
}

setModalButtons(invalidId(id).buttons();

2 Comments

You don't need to, but that's also a valid option.
Why though? Just returning the JSX element directly should be fine as it compiles to a js object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.