MLnewb
MLnewb

Reputation: 43

How to concatenate the strings received from api

I want to highlight the words that are in the "highlight" elements in the "text" element sentence. I can successfully highlight one sentence but I'm not able to concatenate two or more sentences together. I'm only able to show one sentence and it's highlighted word with the code:

this.setState({
  text: result[0].text,
  highlight: result[0].highlight,
});

But not more than more sentence at once. I want to dynamically concatenate as many sentences as there are in the api with the highlighted words. I tried setting the state to text: result[].text and highlight: result[].highlight but it gave me errors. As you can see in this sandbox, only when you do result[0].text or result[1].text, you get the different results but I want to concatenate all the sentences that are in the api dynamically supposing that I will have more sentences in the future.

The react code looks like this:

import React, { Component } from "react";
import { render } from "react-dom";

import "./App.css";

const stripChars = word => word.replace(/[\W_]+/g, "");

class App extends Component {
  state = {
    text: "The gun is a dangerous weapon, don't kill anyone",
    highlight: ["gun", "kill"]
    // text: "",
    // highlight: []
  };

  componentDidMount() {
    fetch("https://api.myjson.com/bins/1ep1fh")
      .then(res => res.json())
      .then(result => {
        console.log(result);
        this.setState({
          text: result[0].text,
          highlight: result[0].highlight
        });
      });
  }
  render() {
    const { text, highlight } = this.state;
    const words = text.split(" ");
    return (
      <div>
        {words.map((word, i) => (
          <span key={i}>
            <span
              className={highlight.includes(stripChars(word)) && "highlight"}
            >
              {word}
            </span>
            &nbsp;
          </span>
        ))}
      </div>
    );
  }
}

export default App;

The CSS file:

.highlight{
  background: red;
}

Upvotes: 2

Views: 1421

Answers (3)

Andr&#233; Reichelt
Andr&#233; Reichelt

Reputation: 1631

Replacing the central part of your code with something similar to this should fix it:

fetch("https://api.myjson.com/bins/1ep1fh")
  .then(res => res.json())
  .then(result => {
    let text = '';
    let highlights = [];

    // This will iterate over every entry in your result
    for(const r of result) {
      // The method will be executed for every entry, called r
      text += r.text;
      highlights.push(...r.highlight);
    }

    this.setState({
      text: text,
      highlight: highlights
    });
  });
}

This is very similar to @Dyo's approach, but it should be a little bit more efficient. He creates a new copy of the whole highlight array plus the entries to add in each iteration, while in this example, we use the Array.push method. This only adds the new values while not duplicating the original values.

Upvotes: 1

Dyo
Dyo

Reputation: 4464

You have to iterate over your api results in order to concatenate them :

  componentDidMount() {
    fetch("https://api.myjson.com/bins/1ep1fh")
      .then(res => res.json())
      .then(result => {
        console.log(result);
        let text = "";
        let highlight = [];
        for (const item of result) {
          text += item.text + '\n';
          highlight = [...highlight, ...item.highlight];
        }
        this.setState({
          text,
          highlight
        });
      });
  }

Edit: some code explanations

highlight = [...highlight, ...item.highlight];

Yes, this is the array spread operator here to create a single array with all words to highlight. (For each loop iteration, it spreads all words from the actual item's highlights in the loop, and also spread the old ones);

You can also do it like this :

for (const word of item.highlight) {
  highlight.push(word);
}

let text = ""; let highlight = [];

This is just variable init, these are new ones, I could name them differently (I should have named them concatenatedTexts and concatenatedHighlights to avoid confusion)

Yes, the state is erased, if you want to keep your initial state and concatenate it too you can change setState like this :

this.setState(prevState => ({
  text: prevState.text + "\n" + text,
  highlight: [...prevState.highlight, ...highlight]
}));

Upvotes: 1

Nico
Nico

Reputation: 7256

You can use Array.Map and join() in your api call for iterate and flat the array :

  componentDidMount() {
    fetch("https://api.myjson.com/bins/1ep1fh")
      .then(res => res.json())
      .then(result => {
        let texts = result
          .map((el, i) => {
            return el.text;
          })
          .join("");
        let highlights = result
          .map((el, i) => {
            return el.highlight;
          })
          .join("").split(",");
        console.log(highlights);
        this.setState({
          text: texts,
          highlight: highlights
        });
      });
  }

result

Upvotes: 2

Related Questions