React中条件渲染的七种实现方式有数据就显示组件,没有数据则什么都不显示。posts是要呈现的列表:exportdefaultfunctionApp(){const{posts}=usePosts();如果(!帖子)返回空;return(
);}这个表单会起作用的原因是我们会提前返回,如果满足条件(posts值不存在),返回null将不会在组件中显示任何内容。当有多个条件要检查时,也可以使用if语句。例如,在显示数据之前检查加载和错误状态:exportdefaultfunctionApp(){const{isLoading,isError,posts}=usePosts();if(isLoading)返回
Loading...
;如果(isError)返回
错误!
;return(
);}这里我们可以多次使用if语句,不需要使用else或者if-eles语句,减少了需要的代码量被写入并且更具可读性。二、三元运算符当我们想提前退出或者什么都不显示的时候,if语句就很有用了。但是如果我们不想写一个与返回的JSX分开的条件,而是直接在其中呢?然后我们可以使用三元表达式来编写条件。在React中,我们必须在JSX中包含表达式,而不是语句。这就是为什么我们只能在JSX中使用三元表达式而不是if语句来编写条件。例如,要在移动设备屏幕上显示一个组件而在更大的屏幕上显示另一个组件,您可以使用三元表达式:exportdefaultfunctionApp(){constisMobile=useWindowSize()return(?
:
})}除了在JSX中包含这些三元表达式,你可以将它们的结果分配给一个变量,然后在你需要的地方使用它:exportdefaultfunctionApp(){constisMobile=useWindowSize();constChatComponent=isMobile?<移动聊天/>:<聊天/>;return(
{ChatComponent})}三、&&运算符很多时候,我们可能想使用三元表达式,但是如果条件不满足,什么都不会被显示。代码看起来像这样:条件?<组件/>:空。这可以使用&&运算符简化:exportdefaultfunctionApp(){const{posts,hasFinished}=usePosts()return(<>
{hasFinished&&(
完成了!
)}>)}如果条件为真,则逻辑&&运算符后的表达式将作为输出。如果条件为假,React将忽略并跳过该表达式。四、switch中的if语句过多会导致组件变得混乱,可以将多个条件提取到一个单独的包含switch语句的组件中(根据组件逻辑的复杂程度来选择是否提取到一个单独的组件中).我们来看一个简单的菜单切换组件:exportdefaultfunctionMenu(){const[menu,setMenu]=React.useState(1);consttoggleMenu=()=>{setMenu((m)=>{if(m===3)return1;returnm+1;});}return(<>
切换菜单>);}functionMenuItem({menu}){switch(menu){case1:返回<用户/>;情况2:返回;案例3:返回;默认值:返回空值;MenuItem组件父菜单组件带有switch语句,不乱条件逻辑,很容易看出对于给定的菜单状态会显示哪个组件。注意,switchcase运算符必须使用默认值,因为在React中,组件总是需要返回一个元素或null。5.枚举在JavaScript中,当一个对象被用作键值对的映射时,它可以作为一个枚举:constENUMOBJECT={a:'1',b:'2',c:'3',};假设你想创建三个不同的组件Foo、Bar和Default,并根据某种状态显示它们:constFoo=()=>{return;};constBar=()=>{return;};constDefault=()=>{return;};创建一个可用作枚举的对象:constENUM_STATES={foo:,bar:,default:};渲染这个枚举对象的函数:functionEnumState({state}){return{ENUM_STATES[state]}
;}上面的状态属性可以从对象中获取值。如您所见,它比switchcase运算符更具可读性。六、JSX库JSXControlStatements库扩展了JSX的功能,让你可以直接使用JSX实现条件渲染。它是一个Babel插件,在转译过程中将类似组件的控制语句翻译成相应的JavaScript。安装babel-plugin-jsx-control-statements包并修改Babel配置后,应用可以这样改写:exportdefaultfunctionApp(props){const[isLoggedIn,setIsLoggedIn]=useState(false);//...返回(/When>);}当然不推荐这样写条件语句,这样会降低代码的可读性,而JSX允许你使用强大的JavaScript特性自己处理条件渲染,无需添加模板组件即可实现.7.高阶组件高阶组件(HOC)是React中条件渲染的完美搭档。HOC可以帮助处理多个用例,但一个用例可能是使用条件渲染更改组件的外观。让我们看看用于显示元素或组件的HOC:}return();};}constListWithLoadingIndicator=withLoadingIndicator(List);functionApp({list,isLoading}){return();}在这个例子中,List组件可以关注呈现列表。而不是再次加载状态。HOC隐藏了来自实际组件的所有干扰。最终,可以添加多个高阶组件来隐藏多个条件渲染边缘情况。注意事项1.小心。让我们看一个常见的渲染示例。只有当数组中有元素时才渲染内容:{gallery.length&&}预期结果是当数组中有元素时才渲染内容。当不存在元素时,不呈现任何内容。但是,我在页面上得到“0”。这是因为在使用AND运算符时会立即返回一个错误的左侧值(如0)。在JavaScript中,布尔算法不会将其结果转换为布尔值。因此,React将结果值放入DOM中,与false不同的是,0是一个有效的React节点,因此它最终会被渲染为0。那么如何避免这个问题呢?您可以将条件显式转换为布尔值。当表达式结果为false时,页面不渲染:gallery.length>0&&jsx!!gallery.length&&jsxBoolean(gallery.length)&&jsx或者用三元表达式实现:{gallery.length?:null}其次,优先级和运算符(&&)比或运算符(||)有更高的优先级。因此,要格外小心包含AND运算符的JSX条件:user.anonymous||user.restricted&&这相当于:user.anonymous||(user.restricted&&)这样当AND运算符左边为真时,会直接返回,不会继续执行后面的代码。因此,在大多数情况下,当你看到or运算符时,将其括在括号中,以避免由于优先级问题而导致渲染错误:{(user.anonymous||user.restricted)&&}三、嵌套三元表达式三元表达式适用于两个JSX之间的切换,一旦超过两个,代码就会变得糟糕:{isEmoji?:isCoupon?:isLoaded&&}有时候用&&来实现会更好,但是有些条件判断会重复:{isEmoji&&}{isCoupon&&}{!isEmoji&&!isCoupon&&isLoaded&&}当然,在这种情况下,使用if语句可能是更好的选择:constgetButton=()=>{if(isEmoji)return;如果(isCoupon)返回;返回已加载?:空;};4.避免将JSX作为条件通过props传递的React元素可以作为判断条件吗?让我们看一个简单的例子:constWrap=(props)=>{if(!props.children)returnnull;返回{props.children}
};我们希望Wrap在没有内容时呈现null,但这不是React的工作方式:props.children可以是一个空数组,例如<哇p>{[].map(e=>)}children.length也失败了:children也可以是单个元素,而不是数组,eg:(换行>)。React.Children.count(props.children)支持单子和多子,但是它会认为{false&&'hi'}{false&&'there'}包含2项,但实际上没有任何子项。React.Children.toArray(props.children)移除无效节点,例如false。但是,对于一个空片段,它仍然是:<><>/>。如何在组件内部移动条件渲染:withDiv=(p)=>p.hide?null:,当Wrap渲染时你永远不知道它是否为null,因为react只会在parent之后渲染子div,有状态的child可以独立于它的parent重新渲染。因此,不要将JSX作为判断条件,以免出现一些不可预知的问题。5.重新安装还是更新?用三元表达式写的JSX感觉就像一个完全独立的代码:{hasItem?:}当hasItem改变时会发生什么?我的猜测是卸载,然后安装,因为这里写了2个单独的JSX标签。然而,React不知道也不关心我们写了什么,它只看到Item元素在同一个地方,所以它保持挂载的实例,更新props。上面的代码相当于。注意:如果三元表达式包含不同的组件,例如{hasItem?:},当hasItem改变时React会重新挂载,因为Item1无法更新为Item2。上述情况会导致一些意想不到的行为:{mode==='name'?:}在这里,如果在name的输入中输入了一些东西,然后切换模式,那么name中输入的内容会泄漏到phone的输入中,这会导致甚至更多地破坏依赖于先前状态的复杂更新机制。这里的一种解决方法是使用密钥。通常,我们用它来渲染列表,但它实际上是React的元素标识提示——具有相同键的元素是相同的逻辑元素:{mode==='name'?:}另一种方法是用两个单独的&&块替换三元表达式。当键不存在时,React回退到子数组中的项目索引,因此将不同的元素放在不同的位置与显式定义键具有相同的效果:{mode==='name'&&}{mode!=='name'&&}参考:https://blog.thoughtspile.tech/2022/01/17/jsx-conditionals/。https://ordinarycoders.com/blog/article/react-conditional-rendering。