【问题标题】:How to concatenate the strings received from api如何连接从api收到的字符串
【发布时间】:2020-01-11 23:31:05
【问题描述】:

我想在“text”元素句子中突出显示“highlight”元素中的单词。我可以成功突出一个句子,但我无法将两个或多个句子连接在一起。我只能显示一个句子,它是用代码突出显示的单词:

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

但一次不能超过多个句子。我想将 api 中尽可能多的句子与突出显示的单词动态连接起来。我尝试将状态设置为text: result[].texthighlight: result[].highlight,但它给了我错误。正如您在this sandbox 中看到的那样,只有当您执行result[0].textresult[1].text 时,您才会得到不同的结果,但我想动态连接api 中的所有句子,假设我将来会有更多句子.

react 代码如下所示:

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;

CSS 文件:

.highlight{
  background: red;
}

【问题讨论】:

  • 如果您的 API 在结果中返回多个元素,您必须遍历结果数组。为此使用for infor of 循环。

标签: javascript reactjs api fetch


【解决方案1】:

您可以在 api 调用中使用 Array.Mapjoin() 来迭代和展平数组:

  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

【讨论】:

  • 使用join(''); 否则你会得到额外的逗号。
  • 为什么在第一句话中还要突出显示'a'
  • @MLnewb,因为您正在使用需要数组作为参数的包含,请检查更新的答案
【解决方案2】:

您必须遍历您的 api 结果才能连接它们:

  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
        });
      });
  }

编辑:一些代码解释

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

是的,这是数组扩展运算符,用于创建一个包含所有要突出显示的单词的数组。 (对于每次循环迭代,它会传播循环中实际项目的亮点中的所有单词,并传播旧的);

你也可以这样做:

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

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

这只是变量 init,这些是新的,我可以不同地命名它们(我应该将它们命名为 concatenatedTextsconcatenatedHighlights 以避免混淆)

是的,状态已被删除,如果您想保持初始状态并将其连接起来,您可以像这样更改setState

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

【讨论】:

  • 这工作.. 谢谢。你能帮我理解一下吗
  • 这只是一个循环来迭代结果数组并从数组对象中选择每个文本并突出显示,你能告诉我你不明白哪一部分吗?
  • 你为什么要让文本又让高亮?因为再次使用它,初始状态会被删除,对吗?因为第一句话应该出现两次,因为我将它设置为最初的状态,它又是 api 中的第一个元素。这也是您正在使用的传播运算符吗? highlight = [...highlight, ...item.highlight];
  • 感谢您的解释。我可以在突出显示的单词上使用下拉菜单吗?这是一个例子:jsfiddle.net/utmkr2ew...我想知道我会在哪里写在 jsfiddle 演示中写的 react js 文件中的 onclick 方法
  • @MLnewb 如果单词突出显示,您可以有条件地渲染&lt;select&gt;(就像您在 className 中所做的那样),您可能需要为此创建一个新问题,因为它很难帮助您像这样的cmets。
【解决方案3】:

用类似的东西替换代码的中心部分应该可以解决它:

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
    });
  });
}

这与@Dyo 的方法非常相似,但应该更高效一些。他创建了整个高亮数组的新副本以及要在每次迭代中添加的条目,而在此示例中,我们使用 Array.push 方法。这只会添加新值,而不复制原始值。

【讨论】:

  • 这将覆盖值和状态将具有最后一个。
  • @jcubic 我明白了。我想,setState 是一种将字符串附加到现有文本的方法。在这种情况下,您必须在此方法中直接进行连接。我已经稍微编辑了它,所以它现在应该可以工作了。
  • 没有任何编辑需要使用text: this.state.text + r.text
  • @jcubic 对不起,我在编辑之前已经发布了。现在应该可以看到编辑了。
  • 现在代码将从输入 ['foo', 'bar'] -> [['f', 'o', 'o'], ['b', 'a', 'r']] 创建,如果您传播字符串,您将获得字符数组,然后将其推入另一个数组。如果您不知道它是如何工作的,请不要使用它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-02
  • 1970-01-01
  • 2015-08-04
  • 1970-01-01
  • 1970-01-01
  • 2014-03-31
  • 1970-01-01
相关资源
最近更新 更多