【问题标题】:Change Button Text in loop using React使用 React 在循环中更改按钮文本
【发布时间】:2021-12-26 05:35:34
【问题描述】:

是否可以更改使用数组创建的按钮文本。如果可能的话,我应该如何处理按钮中的 onClick 功能。这是示例代码:

function RenderFeeds(props) {
const list = []

props.products.forEach((product) => {
  list.push(
    <>
       <h1>{product.name}</h1>
       <h2>{product.company_name}</h2>
       <h2>{product.description}</h2>
        <button onClick={}>{product.watchlist==false ? 'Add to watchlist':'Remove From watchlist'}</button>
    </>
  )
})

return (
  <>
    {list}
  </>
)}

所以基本上我有一个包含这个值的数组:

[{
"name": "lorem ipsum",
"description": "Nam vel nisi rutrum quam ",
"company_name": "PT dapibus ",
"company_slug": "pt-dapibus",
"watchlist": true,
"id": 1
}]

我正在使用这个数组创建组件。 watchlist 变量将影响按钮中的文本。如果它是true,那么我希望按钮具有从监视列表中删除,反之亦然。

我知道我们可以在 React 中使用钩子并将 useState 应用于 onClick 按钮功能。但是如果我使用循环创建组件,我不知道如何初始化状态。

【问题讨论】:

    标签: javascript reactjs react-native ecmascript-6 react-hooks


    【解决方案1】:

    在下面的 sn-p 中,我实现了一个示例,为了简单起见,我使用静态数据作为列表。我希望它可以帮助。

    const data = [{ "name": "lorem ipsum", "description": "description1", "company_name": "PT dapibus ", "company_slug": "pt-dapibus", "watchlist": true, "id": 1 },{ "name": "lorem ipsum2", "description": "description2", "company_name": "Google", "company_slug": "company_slug", "watchlist": true, "id": 2 }]
    
    function RenderFeeds({ feeds, onAddToWatch, onRemoveFromWatch }) {
      return (
        <React.Fragment>{/* or any markup you want */}
          {feeds.map((feed) => (
            <div className="feed" key={feed.id}>
              <h1>{feed.name}</h1>
              <h2>{feed.company_name}</h2>
              <h2>{feed.description}</h2>
              <button
                onClick={() =>
                  feed.watchlist
                    ? onRemoveFromWatch(feed.id)
                    : onAddToWatch(feed.id)
                }
              >
                {feed.watchlist ? 'Remove From watchlist' : 'Add to watchlist'}
              </button>
            </div>
          ))}
        </React.Fragment>
      );
    }
    
    function Feed() {
      const [feeds, setFeeds] = React.useState([]);
    
      React.useEffect(() => {
        //receiving data, for example fetching data by ajax or whatever
        setFeeds(data);
      }, []);
    
      const handleAddToWatch = (id) => {
        // implement updating feeds, for example making an ajax request and getting new data
        setFeeds((feeds) =>
          feeds.map((feed) => ({
            ...feed,
            watchlist: feed.id == id ? true : feed.watchlist,
          }))
        );
      };
      const handleRemoveFromWatch = (id) => {
        // implement updating feeds, for example making an ajax request and getting new data
        setFeeds(feeds =>
          feeds.map((feed) => ({
            ...feed,
            watchlist: feed.id == id ? false : feed.watchlist,
          }))
        );
      };
    
      return (
          <RenderFeeds
            feeds={feeds}
            onAddToWatch={handleAddToWatch}
            onRemoveFromWatch={handleRemoveFromWatch}
          />
      );
    }
    
    ReactDOM.render(<Feed/>, document.getElementById('root'))
    .feed{
      border: 2px solid #ccc;
      padding: 15px;
      margin: 15px;
    }
    
    .feed h1{ margin: 0}
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
    
    <div id="root"></div>

    【讨论】:

      【解决方案2】:

      如果你是基于 props 渲染东西,那么在这种情况下就没有必要使用钩子了。

      这样的事情应该可以工作:

      function RenderFeeds(props) {
      
      return (
        <>
          {props.products.map((product) => {
            return (
              <>
                <h1>{product.name}</h1>
                <h2>{product.company_name}</h2>
                <h2>{product.description}</h2>
                <button onClick={}>{product.watchlist==false ? 'Add to watchlist':'Remove From watchlist'}</button>
              </>
            )
          })}
        </>
      )}
      

      【讨论】:

        【解决方案3】:

        无需创建一个额外的变量list 并循环遍历您作为道具获得的产品列表,然后将其推送到list,然后渲染list 您可以直接循环产品列表使用map。并且不用检查product.watchlist==false什么时候可以使用Logical NOT

        function RenderFeeds(props) {
        
        return (
          <>
            {props.products.map((product) => {
              return (
                <>
                  <h1>{product.name}</h1>
                  <h2>{product.company_name}</h2>
                  <h2>{product.description}</h2>
                  <button onClick={}>{!product.watchlist ? 'Add to watchlist':'Remove From watchlist'}</button>
                </>
              )
            })}
          </>
        )}
        

        【讨论】:

        • 非常感谢您的建议。但是如何更新 product.watchlist 值?因为我希望按钮触发 product.watchlist 值,以便按钮文本可以在“添加到关注列表”和“从关注列表中删除”之间切换
        【解决方案4】:

        首先,我强烈建议您使用 Array.map() 方法而不是使用 Array.forEach() 来创建 List 组件数组,因为 Array.map() 本身会返回一个带有新映射的数组。

        你在解决这个问题时寻找的东西或概念称为conditional rendering

        您可以使用ternary operator 或也称为conditional operators 来执行conditional rendering,因为JSX expects an expression 可以评估为某事。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-20
          • 1970-01-01
          • 2021-05-23
          • 2020-10-10
          • 1970-01-01
          • 2017-07-26
          相关资源
          最近更新 更多