React - 显示隐藏两个元素而不在页面加载时闪烁
React - show hide two elements without flickering on page load
编辑。 我重写了代码,使其更加简约。下面的代码是我的问题的峰值测试。
这是问题的视频:
我有两个组件。
第一个组件名为 TextEditor(它是一个文本编辑器),但它的内容无关紧要 - 该组件可以是任何东西。带有文本的简单 div 也同样重要。
下一个组件名为 Workflows,用于呈现来自 IndexDB 的集合(使用 Dexie.js 库)。我将此集合命名为 "workflows",并将它们存储在其中的状态变量命名为 workflows_list_array
我想做的是:
当页面加载时,我想检查是否有任何工作流具有特定 ID。如果他们这样做,我将它们存储在 workflows_list_array 中并渲染它们。我不需要这部分的帮助。
但是,如果不存在符合上述条件的工作流,我想隐藏名为 Workflows 的组件并呈现名为 TextEditor 的组件。如果确实存在工作流,我希望隐藏 TextEditor 并显示工作流
问题是,即使我让它工作,当工作流确实存在时(当填充 workflows_list_array 时)TextEditor "flickers" 在隐藏之前短暂地显示,然后显示工作流组件。
我知道这是一个异步问题,但我不知道如何解决它。
我在下面发布了代码,并尽量减少它。
Test.js
import React, {useState, useEffect} from "react";
import db from "../services"
function Workflows(props){
return (
<div>
<ul>
{
props.workflows.map((val,index)=>{
return <li key={index}>{val.content}</li>
})
}
</ul>
</div>
)
}
function TextEditor(){
return (
<div> TextEditor </div>
)
}
function Test(props){
let [workflows_list_array, set_state_of_workflows_list_array] = useState([]);
let [client_id_number, set_client_id_number] = useState(5);
useEffect(() => { // get all workflows of the selected client per its ID
db.workflows.toArray((workflows_list)=>{ // iterate through workflows array
return workflows_list
}).then((workflows_list)=>{
workflows_list.forEach((val)=>{
if(client_id_number === val.client_id){
set_state_of_workflows_list_array((prev)=>{
return [...prev, val]
});
}
});
});
}, []);
return(
<div>
{workflows_list_array.length ? null : <TextEditor/> }
{workflows_list_array.length ? <Workflows workflows={workflows_list_array}/> : null}
</div>
)
}
export default Test
services.js
import Dexie from 'dexie';
import 'dexie-observable';
var workflowMagicUserDB = new Dexie("WorkflowMagicUserDB");
workflowMagicUserDB.version(1).stores({
user: "",
workflows: "++id,client_id,content,title",
clients: "++id,name",
calendar_events: "++id,start,end,title"
});
export default workflowMagicUserDB
你为什么不包含一个标志来指示你是否已经从 IndexDB 获得数据,比如:
function Test(props){
const [loading, setLoading] = React.useState(true);
let [workflows_list_array, set_state_of_workflows_list_array] = useState([]);
let [client_id_number, set_client_id_number] = useState(5);
useEffect(() => {
db.workflows.toArray((workflows_list)=>{
}).then((workflows_list)=>{
}).finally(() => setLoading(false)); //when process finishes, it will update the state, at that moment it will render TextEditor or Workflows
}, []);
if(loading) return <LoadingIndicator/>; // or something else which indicates the app is fetching or processing data
return(
<div>
{workflows_list_array.length ? null : <TextEditor/> }
{workflows_list_array.length ? <Workflows workflows={workflows_list_array}/> : null}
</div>
)
}
export default Test
当进程完成时,finally
将被执行并将 loading
状态设置为 false,之后,您的应用将呈现 TextEditor
或 Workflows
编辑。 我重写了代码,使其更加简约。下面的代码是我的问题的峰值测试。
这是问题的视频:
我有两个组件。
第一个组件名为 TextEditor(它是一个文本编辑器),但它的内容无关紧要 - 该组件可以是任何东西。带有文本的简单 div 也同样重要。
下一个组件名为 Workflows,用于呈现来自 IndexDB 的集合(使用 Dexie.js 库)。我将此集合命名为 "workflows",并将它们存储在其中的状态变量命名为 workflows_list_array
我想做的是:
当页面加载时,我想检查是否有任何工作流具有特定 ID。如果他们这样做,我将它们存储在 workflows_list_array 中并渲染它们。我不需要这部分的帮助。
但是,如果不存在符合上述条件的工作流,我想隐藏名为 Workflows 的组件并呈现名为 TextEditor 的组件。如果确实存在工作流,我希望隐藏 TextEditor 并显示工作流
问题是,即使我让它工作,当工作流确实存在时(当填充 workflows_list_array 时)TextEditor "flickers" 在隐藏之前短暂地显示,然后显示工作流组件。
我知道这是一个异步问题,但我不知道如何解决它。
我在下面发布了代码,并尽量减少它。
Test.js
import React, {useState, useEffect} from "react";
import db from "../services"
function Workflows(props){
return (
<div>
<ul>
{
props.workflows.map((val,index)=>{
return <li key={index}>{val.content}</li>
})
}
</ul>
</div>
)
}
function TextEditor(){
return (
<div> TextEditor </div>
)
}
function Test(props){
let [workflows_list_array, set_state_of_workflows_list_array] = useState([]);
let [client_id_number, set_client_id_number] = useState(5);
useEffect(() => { // get all workflows of the selected client per its ID
db.workflows.toArray((workflows_list)=>{ // iterate through workflows array
return workflows_list
}).then((workflows_list)=>{
workflows_list.forEach((val)=>{
if(client_id_number === val.client_id){
set_state_of_workflows_list_array((prev)=>{
return [...prev, val]
});
}
});
});
}, []);
return(
<div>
{workflows_list_array.length ? null : <TextEditor/> }
{workflows_list_array.length ? <Workflows workflows={workflows_list_array}/> : null}
</div>
)
}
export default Test
services.js
import Dexie from 'dexie';
import 'dexie-observable';
var workflowMagicUserDB = new Dexie("WorkflowMagicUserDB");
workflowMagicUserDB.version(1).stores({
user: "",
workflows: "++id,client_id,content,title",
clients: "++id,name",
calendar_events: "++id,start,end,title"
});
export default workflowMagicUserDB
你为什么不包含一个标志来指示你是否已经从 IndexDB 获得数据,比如:
function Test(props){
const [loading, setLoading] = React.useState(true);
let [workflows_list_array, set_state_of_workflows_list_array] = useState([]);
let [client_id_number, set_client_id_number] = useState(5);
useEffect(() => {
db.workflows.toArray((workflows_list)=>{
}).then((workflows_list)=>{
}).finally(() => setLoading(false)); //when process finishes, it will update the state, at that moment it will render TextEditor or Workflows
}, []);
if(loading) return <LoadingIndicator/>; // or something else which indicates the app is fetching or processing data
return(
<div>
{workflows_list_array.length ? null : <TextEditor/> }
{workflows_list_array.length ? <Workflows workflows={workflows_list_array}/> : null}
</div>
)
}
export default Test
当进程完成时,finally
将被执行并将 loading
状态设置为 false,之后,您的应用将呈现 TextEditor
或 Workflows