【问题标题】:React.js: slice() twice and map()?React.js:两次切片()和映射()?
【发布时间】:2021-07-17 17:24:00
【问题描述】:

我的useState() 应该返回粗体文本(有 * 星 *)和换行符(有 /n)。

所以我想到了使用split() 和map(),但同时使用这两种方法时代码无法正常工作:

let [abt, setAbt] = React.useState([]);
let abtTxt = `I have /n *stars* and /n *lines*`

setAbt(abtTxt.split('*')) // creating the bolded text
setAbt(abtTxt.split(/\n/)) // creating the line breaks

return (
   // bolding every two occasions:
      abt.map((boldSlice, i) => <span key={i} style={ i % 2 !== 0 ? {fontWeight: "bold"} : {} }> {boldSlice} </span>)
   // creating line breaks:
     .map(lineSlice => <> {lineSlice} <br/> </>)
 )

我该怎么办?可能是其他危险的内部 HTML 之类的东西?

谢谢!

【问题讨论】:

  • 第二次调用 setAbt 将替换第一次调用的结果...
  • 你可以只使用 Markdown 库。

标签: arrays reactjs object split jsx


【解决方案1】:

你可以这样做

test = `I have /n *stars* and /n *lines*`;
test1 = test.split("/n");
test1.reduce((acc1, cur1) => {
  cur1 = cur1.split("*").reduce((a1, c1, i1) => {
    a1.push(
      <span key={i1} style={i1 % 2 !== 0 ? { fontWeight: "bold" } : {}}>
        c1
      </span>
    );
    return a1;
  }, []);
  acc1.push(...cur1, </br>);
  return acc1;
}, []);

【讨论】:

  • 我喜欢你的解决方案 :)
  • 有一个错误:应该是&lt;br/&gt;而不是&lt;/br&gt;
  • 好的,谢谢`
  • 好主意,但是在尝试在粗体文本中换行时它不起作用 - 粗体只在中断之前发生:I have /n *stars /n and /n lines* 将返回 我有 stars 和线条
  • 您可以稍微修改一下,它会相应地工作。 ; )
【解决方案2】:

你可以用capturing parentheses进行拆分,然后对每一项进行测试,并进行相应的格式化:

const bolden = /\*[^*]*\*/;
const lineBreak = /\/n/;
const all = new RegExp(`((?:${bolden.source}) | (?:${lineBreak.source}))`);

const removeAsterisks = str => str.replace(/\*/g, '')

const formatText = str => {
  let i = 0;
  
  return str.split(all)
    .map(s => {
      if(bolden.test(s)) return i++ % 2 ? removeAsterisks(s) : (
        <b>{removeAsterisks(s)}</b>
      );

      if(lineBreak.test(s)) return (<br />);

      return s;
    });
}

const Demo = ({ str }) => (
  <span>
    {
      formatText(str)
    }
  </span>
);

ReactDOM.render(
  <Demo str="I have /n *stars* and /n *lines*" />,
  root
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

【讨论】:

  • 我认为有一个错误:lines应该是bold,但不是。
  • 看问题中“每两次加粗”的注释。
【解决方案3】:

试试这个:

const LineComponent = ({line}) => {
  const style = index => ({fontWeight: index % 2 === 1 ? '700' : '400'});
  return (
    <span>{line.split('*').map((part, index) => (
      <span key={index} style={style(index)}>{part}</span>
    ))}
    </span>
  );
}

const TextComponent = ({str}) => {
  return (
    <div>
      {str.split(/\n/).map((line, index) => {
        return (
          <div key={index}>
            <LineComponent line={line}  />
            {index > 0 && <br/>}
          </div>
        );
      })}
    </div>
  );
}

ReactDOM.render(
  <TextComponent str={`I have \n *stars* and \n *lines*`} />,
  document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="container">
</div>

这是另一个没有嵌套顺序的新行/粗体分隔符:

const TextComponent = ({str}) => {
const html = str.split('*').reduce((s, p, i) => `${s}${i % 2 === 1 ? `<b>${p}</b>` : p}`, '').replaceAll('\n', '<br/>');
return (<span dangerouslySetInnerHTML={{__html: html}} />);
} 

ReactDOM.render(
  <TextComponent str={`I have \n *stars and \n lin*es`} />,
  document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="container">
</div>

【讨论】:

  • 我非常喜欢您的解决方案,但是当尝试在粗体文本中间换行时它不起作用:I have \n *stars and \n lin*es 将返回:我有 星和 林es
  • @matancl 我在答案中添加了另一个 sn-p,它可以工作
【解决方案4】:

你不应该在组件的渲染中调用 setState 或 useState 设置器。

您可以编写一个简单的函数来完成这项工作并在渲染中使用它。

类似的东西:

    const abtTxt = `I have /n *stars* and /n *lines*`;
    const abt = parseRawText(abtTxt);

【讨论】:

    猜你喜欢
    • 2015-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-02
    相关资源
    最近更新 更多