1

I'm mapping data from a JSON to a React component, where part of the strings from the JSON are replaced by values from Context. This works perfectly for JSON that only has a single level.

This works:

/* JSON */
const data = {
  "content":[
    "#number# Tips to Get #goal#",
    "Your Search For #goal# Ends Here"
  ]
}

const parameters = useContext(ParameterContext)
  const {
    audience,
    goal,
    number
  } = parameters;

const content = data.content;

const listItems = content.map(
  (result, index) => 
  <li key={index}>{Object.keys(parameters).reduce((res, key) => 
    res.replace(`#${key}#`, parameters[key]), result)}</li>
);

...

return (
  <ul>
    {listItems}
  </ul>
)

However, when I introduce another level of nesting to my JSON data, the .map() function breaks. For example:

{
  "content": [
    {
      "text" : "#number# Tips to Get #goal#",
      "types" : [ "email"]
    },
    {
      "text" : "Your Search For #goal# Ends Here",
      "types" : [ "ad", "email" ]
    }
  ]
}

Trying to parse that results in TypeError: res.replace is not a function. Now, I suspect that's because the target text strings are now inside another array, but I can't figure out how to reach them in my map() function.

How would I fix the map() function to read the text strings in the update JSON format?

4 Answers 4

1

This should work

    const listItems = content.map((result, index) => (
    <li key={index}>
        {Object.keys(parameters).reduce((res, key) => {
            return res.replace(`#${key}#`, parameters[key]);
        }, result.text)} //result -> result.text
    </li>
));
Sign up to request clarification or add additional context in comments.

Comments

0

Use reduce to accrue the li elements in an array. Modify the text property by using the values of the object keys

const obj = {
  "content": [{
      "text": "#number# Tips to Get #goal#",
      "types": ["email"]
    },
    {
      "text": "Your Search For #goal# Ends Here",
      "types": ["ad", "email"]
    }
  ]
}


const parameters = {
  audience: 'audience1',
  goal: 'goal1',
  number: 'number1'
}

const keys = Object.keys(parameters)

const listItems = obj.content.reduce((acc, x, i) => {
  keys.forEach(key => {
    x.text = x.text.replace(`#${key}#`, parameters[key])
  })
  acc.push(`<li key=${i}> ${x.text}</li>`);
  return acc;
}, []);


console.log(listItems)

Comments

0
private menu: Object = {
  "content": [
    {
      "text" : "#number# Tips to Get #goal#",
      "types" : [ "email"]
    },
    {
      "text" : "Your Search For #goal# Ends Here",
      "types" : [ "ad", "email" ]
    }
  ]
};

public buildMenu():void
{
    let html: string  = '<ul>';
    this.menu.forEach( (menuItems) => html += buildMenuSubMenu(menuItem) );
    html += '</ul>'
}

private buildMenuSubMenu(menuItem): string
{
    let html: string = null;

    html += `<li><a href='${menuItem[types][0]}'>${menuItem[text]}</a>`;

    if (menuItem.lenght)
    {
        html += '<ul>';
        menuItem.forEach( (child) => html += buildMenuSubMenu(child) );
        html += '</ul>';
    }

    html += '<li>';

    return html;
}

Comments

0

To access the text inside of the object you can use destructuring.

const listItems = content.map(({ text }, index) => (
  <li key={index}>
    {Object.keys(parameters).reduce(
      (res, key) => res.replace(`#${key}#`, parameters[key]),
      text
    )}
  </li>
))

Comments

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.