'Rendering components based on response React JS

I'm trying to render button component based on the API response.

Button response structure

 "buttons": {
                   "yesButton": {
                      "buttonText": "Yes",
                   },
                   "noButton": {
                      "buttonText": "No"
                   }
                }

componentContent.buttons is returning two objects with button contents and the data is getting printed in the console.

But in the view I'm not seeing any buttons html.

What I'm doing wrong here?

 const renderComponentButtons = () => {
if (componentContent?.buttons) {
  console.log(componentContent?.buttons);
  Object.keys(componentContent.buttons).forEach((key) => {
    console.log(key);
    return (
      <ButtonAction
        aria-label={componentContent.buttons[key].buttonText}
        onClick={() => {
          props.toPrev();
        }}
      >
        {componentContent.buttons[key].buttonText}
      </ButtonAction>
    );
  });
}
};

  return (
      <div className="row">
        <div className="col-md-4">
          {renderComponentButtons()}
        </div>
      </div>
)


Solution 1:[1]

-Change forEach to map and add return to the start

renderComponentButtons()

const renderComponentButtons = () => {
    if (componentContent?.buttons) {
      console.log(componentContent?.buttons);
      return(Object.keys(componentContent.buttons).map((key, index) => (
        <button
        key={index}
            aria-label={componentContent.buttons[key].buttonText}
            onClick={() => {
              // props.toPrev();
            }}
          >
            {componentContent.buttons[key].buttonText}
          </button>)
      ))
          }
  };

visit CodeSandbox to play around with the code.

The output: enter image description here

Solution 2:[2]

ForEach return undefined so use map instead of forEach like this

Object.keys(componentContent.buttons).map((key) => {   // change this line
  console.log(key);
  return (
    <ButtonAction
      aria-label={componentContent.buttons[key].buttonText}
      onClick={() => {
        props.toPrev();
      }}
    >
      {componentContent.buttons[key].buttonText}
    </ButtonAction>
  );
});

Using map you can avoid the return statement by replacing the curly brackets by parenthesis like this

Object.keys(componentContent.buttons).map((key) => ( 
  <ButtonAction
    aria-label={componentContent.buttons[key].buttonText}
    onClick={() => {
      props.toPrev()
    }}
  >
    {componentContent.buttons[key].buttonText}
  </ButtonAction>
)

Solution 3:[3]

Your code is almost correct, but you should use map instead of forEach and return results from renderComponentButtons.

forEach is for looping through all values in an array and does not expect returned results. map is different, it is used to get returned results.

In your case, your buttons' components need to be returned from the loop

const renderComponentButtons = () => {
  if (componentContent?.buttons) {
    console.log(componentContent?.buttons);
    return Object.keys(componentContent.buttons).map((key) => {
      console.log(key);
      return (
        <ButtonAction
          aria-label={componentContent.buttons[key].buttonText}
          onClick={() => {
            props.toPrev();
          }}
          key={key}
        >
          {componentContent.buttons[key].buttonText}
        </ButtonAction>
      );
    });
  }
  return null; //no buttons in your data
};

return (
  <div className="row">
    <div className="col-md-4"> {renderComponentButtons()} </div>
  </div>
);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3