如何在单击Syncfusion的TabComponent标题时正确更新内容

huangapple go评论52阅读模式
英文:

How to properly update content when clicking on a header of Syncfusion's TabComponent

问题

我需要使用Syncfusion的TabComponent在Web应用程序中显示一些文件。可能会有很多文件,但我只想逐个显示它们在我的选项卡中。如果我只想显示一个文件,我也不想在页面开始时存储所有其他文件。我只想加载显示的文件,其他文件将在用户希望查看它们并且仅在那一时刻被调用,以避免存储过多负担。

因此,我尝试了一些方法,以便在隐藏的选项卡中具有一个空的div,并在焦点选项卡中显示一些内容。这个示例只是关于将填充的div更新为一个空的div,反之亦然。

import { TabComponent, TabItemDirective, TabItemsDirective } from '@syncfusion/ej2-react-navigations';
import * as React from 'react';
import { useState } from 'react';
import ReactDOMServer from 'react-dom/server';

const Tab = (props) => {
    const tabContent = (data) => {
        return ReactDOMServer.renderToStaticMarkup(data);
    };

    const headertext = [{ text: 'Header1', id: "0" }, { text: 'Header2', id: "1" }, { text: 'Header3', id: "3" }];
    const [chosenItem, setChosenItem] = useState(1);
    const [counter, setCounter] = useState(0);
    const contentToBeShown = [<div>Content1</div>, <div>Content2</div>, <div>Content{counter}</div>];
    const [content, setContent] = useState(contentToBeShown);

    const selecting = (args) => {
        setCounter(counter + 1);
        console.log(args);
        content.forEach((item, index) => {
            if (index !== args.selectingIndex) {
                content[index] = (<div>no</div>);
            } else {
                console.log("Before content", content, "contentToBeShown", contentToBeShown);
                content[index] = contentToBeShown[index];
                console.log("After content", content, "contentToBeShown", contentToBeShown[index]);
            }
        });
    };

    return (
        <div className="control-pane">
            <div className="control-section tab-control-section">
                {/* Render the Tab Component */}
                <TabComponent overflowMode="Scrollable" id="defaultTab" selecting={selecting} selectedItem={chosenItem}>
                    <TabItemsDirective>
                        {
                            // Create TabItemDirective model dynamically
                            headertext.map((item, index) => {
                                return <TabItemDirective presentation={true} key={index} header={item} content={{ template: tabContent, data: content[index] }} />;
                            })
                        }
                    </TabItemsDirective>
                </TabComponent>
            </div>
        </div>
    );
};
export default Tab;

使用此代码,我可以看到焦点选项卡应该返回具有其简单内容的div。在console.log中,内容从"no" div更改为填充的div,正如预期的那样。但是,在渲染的页面上,仍然显示旧的"no" div。

感觉好像在渲染过程中选择函数发生得太晚,无法显示正确的内容,但即使在这里我可能也是错的。是什么导致了渲染失败,我该如何解决这个问题?

英文:

I need to use the TabComponent from Syncfusion to show some files in a web app. There can be a lot of files, but I only want to show them one by one in my tabs. And if I want to show only one file, I also DON'T want to store all the other files at the start of the page. I just want to load the file that is shown, and all the other ones will be called later, when the user wants to see them and only at that moment to avoid too much charge in the storage.

So I tried a few things to be able to have an empty div in the hidden tabs, and something shown in the focused tab. This example is just about updating a filled div to an empty one and vice versa.

import { TabComponent, TabItemDirective, TabItemsDirective } from &#39;@syncfusion/ej2-react-navigations&#39;;
import * as React from &#39;react&#39;;
import { useState } from &#39;react&#39;
import ReactDOMServer from &#39;react-dom/server&#39;

const Tab = (props) =&gt; {
    const tabContent = (data) =&gt; {
        return ReactDOMServer.renderToStaticMarkup(data);
    };

      const headertext = [{ text: &#39;Header1&#39;, id: &quot;0&quot; }, { text: &#39;Header2&#39;, id: &quot;1&quot; }, { text: &#39;Header3&#39;, id: &quot;3&quot; }];
      const [chosenItem, setChosenItem] = useState(1)
      const [counter, setCounter] = useState(0)
      const contentToBeShown = [&lt;div&gt;Content1&lt;/div&gt;, &lt;div&gt;Content2&lt;/div&gt;, &lt;div&gt;Content{counter}&lt;/div&gt;];
      const [content, setContent] = useState(contentToBeShown)

      const selecting = (args) =&gt; {
        setCounter(counter + 1)
        console.log(args)
        content.forEach((item, index) =&gt; {
            if(index !== args.selectingIndex){
                content[index] = (&lt;div&gt;no&lt;/div&gt;)
            }else{
                console.log(&quot;Before content&quot;, content, &quot;contentToBeShown&quot;, contentToBeShown)
                content[index] = contentToBeShown[index]
                console.log(&quot;After content&quot;, content, &quot;contentToBeShown&quot;, contentToBeShown[index])
            }
        })
      }

      return (
        &lt;div className=&quot;control-pane&quot;&gt;
          &lt;div className=&quot;control-section tab-control-section&quot;&gt;
            {/* Render the Tab Component */}
            &lt;TabComponent overflowMode=&quot;Scrollable&quot; id=&quot;defaultTab&quot; selecting={selecting} selectedItem={chosenItem}&gt;
              &lt;TabItemsDirective&gt;
                {
                    // Create TabItemDirective model dynamically
                    headertext.map((item, index) =&gt; {
                        return &lt;TabItemDirective presentation={true} key={index} header={item} content={{template: tabContent, data: content[index]}}/&gt;
                    })
                }
              &lt;/TabItemsDirective&gt;
            &lt;/TabComponent&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      );
}
export default Tab;

With this code, I can see that the focused tab is SUPPOSED to return my div with its simple content. In the console.log, the content changes from the "no" div to the filled div, just as expected. But, on the rendered page, the old "no" div is still shown.
It feels like there is something about the selecting function happening too late in the rendering process to show the right content but even here I might be wrong.
What causes the failed rendering and how can I get around this problem ?

答案1

得分: 0

我明白问题出在哪里:问题实际上是我在更新状态中的数组 "content" 的方式。

而不是这样做:

content[index] = (<div>no</div>)

你应该像这样更新状态中的数组:

var newContent = []
content.forEach((item, index) => {
   var updateContent = (<div>no</div>)
   if(index === args.selectingIndex){
      updateContent = contentToBeShown[index]
   }
   newContent.push(updateContent)
})
setContent(newContent)
英文:

I understood what was the problem : It was simply the way that I was updating the array "content" in the state.

Instead of doing :

content[index] = (&lt;div&gt;no&lt;/div&gt;)

You have to update an array in a state like this :

var newContent = []
content.forEach((item, index) =&gt; {
   var updateContent = (&lt;div&gt;no&lt;/div&gt;)
   if(index === args.selectingIndex){
      updateContent = contentToBeShown[index]
   }
   newContent.push(updateContent)
})
setContent(newContent)

huangapple
  • 本文由 发表于 2023年7月10日 23:39:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76655308.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定