当前位置: 首页 > 科技观察

你可能需要的React开发技巧!

时间:2023-03-20 13:39:59 科技观察

大家好,我叫CUGGZ。今天我将分享10个编写更干净的React代码的实用技巧!1.JSX简写如何将真实值传递给给定的props?在下面的示例中,propshowTitle用于在navbar组件中显示应用程序的标题:exportdefaultfunctionApp(){return(

);}functionNavbar({showTitle}){return(
{showTitle&&

Title

}
)}在这里,showTitle被显式设置为booleantrue,这是不必要的,因为组件提供Anyprop有一个默认值为真。所以只需要在调用组件的时候传一个showTitle即可:{showTitle&&

Title

}
)}另外,当需要传递一个字符串作为props时,不需要使用花括号{}wrap,可以使用doublequotes把字符串内容包起来传过去:exportdefaultfunctionApp(){return(
);}functionNavbar({title}){return(

{title}

)}2.将不相关的代码移动到单独的组件中编写更简洁的React代码最简单也是最重要的方法是善于将代码抽象为单独的组件React组件。让我们看一个例子。应用顶部会有一个导航栏,会遍历posts中的数据渲染文章标题:exportdefaultfunctionApp(){constposts=[{id:1,title:"Title1"},{id:2,title:"标题2"}];return(
    {posts.map(post=>({post.title}))}
);}functionNavbar({title}){return(

{title}

);}那么我们如何让这段代码更简洁呢?我们可以抽象循环中的代码(帖子标题)并将它们提取到一个单独的组件中,称为FeaturedPosts。提取出来的代码如下:

{title}

);}functionFeaturedPosts(){constposts=[{id:1,title:"Title1"},{id:2,title:"标题2"}];返回(
    {posts.map((post)=>({post.title}))}
);}可以看到,在App组件中,通过组件名称:Navbar和FeaturedPosts,可以快速看出应用的作用。3.为每个组件创建一个单独的文件在上面的例子中,我们在一个文件中实现了三个组件。如果组件逻辑少,这些写是没有问题的,但是如果组件逻辑比较复杂,这样写的代码可读性就很差。为了使您的应用程序文件更具可读性,您可以将每个组件放在一个单独的文件中。这可以帮助我们在应用程序中分离关注点。这意味着每个文件只负责一个组件,如果你想在你的应用程序中复用它,你不会混淆组件的来源://src/App.jsimportNavbarfrom'./components/Navbar.js';从'./components/FeaturedPosts.js'导入FeaturedPosts;导出默认函数App(){return(
);}//src/组件/导航栏。jsexport默认函数Navbar({title}){return(

{title}

);}//src/components/FeaturedPosts.jsexport默认函数FeaturedPosts(){constposts=[{id:1,title:"标题1"},{id:2,title:"标题2"}];return(
    {posts.map((post)=>({post.title}))}
);}此外,通过包括每个单独的组件在其自己的文件中,您可以防止一个文件变得过于臃肿。4.将共享函数移动到React挂钩中在FeaturedPosts组件中,假设您想从API获取帖子数据而不是使用虚假数据。这可以使用fetchAPI来实现:importReactfrom'react';导出默认函数FeaturedPosts(){const[posts,setPosts]=React.useState([]);React.useEffect((){fetch('https://jsonplaceholder.typicode.com/posts').then(resres.json()).then(datasetPosts(data));},[]);return(
    {posts.map((post)=>({post.title}))}
);}但是如果你想怎么办在多个组件中执行此数据请求?假设除了FeaturedPosts组件之外,还有另一个名为Posts的组件包含相同的数据。我们必须复制获取数据的逻辑并将其粘贴到该组件中。为避免重复代码,定义一个新的React钩子,将其命名为useFetchPosts:importReactfrom'react';导出默认函数useFetchPosts(){const[posts,setPosts]=React.useState([]);反应.useEffect((){fetch('https://jsonplaceholder.typicode.com/posts').then(resres.json()).then(datasetPosts(data));},[]);returnposts;}这样它就可以在任何组件中重用,包括FeaturedPosts组件:importuseFetchPostsfrom'../hooks/useFetchPosts.js';exportdefaultfunctionFeaturedPosts(){constposts=useFetchPosts()return(
    {posts.map((post)=>({post.title}))}
);}5.从JSX中移除JS另一个简化的组件最好的方法是从JSX中移除尽可能多的JavaScript。看下面的例子:importuseFetchPostsfrom'../hooks/useFetchPosts.js';导出默认函数FeaturedPosts(){constposts=useFetchPosts()return(
    {posts.map((post)=>({console.log(event.target,'clicked!');}}key={post.id}>{post.title}))}
);}这里我们尝试处理文章的点击事件,你可以看到我们的JSX变得更难阅读了。鉴于该函数作为内联函数包含在内,它掩盖了该组件及其相关函数的用途。那么如何解决这个问题呢?包含onClick的内联函数可以提取到一个单独的处理函数中,将其命名为handlePostClick。这使得JSX更具可读性:importuseFetchPostsfrom'../hooks/useFetchPosts.js';导出默认函数FeaturedPosts(){constposts=useFetchPosts()functionhandlePostClick(event){console.log(event.target,'clicked!');}return(
    {posts.map((post)=>({post.title}))}
);}6.格式化内联样式在JSX中编写过多的内联样式会使代码更难阅读和臃肿:"标题"/>);}functionNavbar({title}){return({title}
)}我们希望将尽可能多的内联样式移动到CSS样式表中。或者将它们组织成对象:exportdefaultfunctionApp(){conststyles={main:{textAlign:"center"}};return();}functionNavbar({title}){conststyles={div:{marginTop:"20px"},h1:{fontWeight:"粗体"}};return({title}
);}一般情况下,最好把这些样式写在CSS中样式表。如果样式需要动态生成,可以在对象中定义。7.使用可选链运算符在JavaScript中,我们需要确保一个对象存在,然后才能访问它的属性。如果对象的值为undefined或null,则会导致类型错误。让我们看一个示例,用户可以在其中编辑他们发布的帖子。只有在isPostAuthor为true时才会显示EditButton组件,也就是说,如果经过身份验证的用户的id与帖子作者的id相同。导出默认函数EditButton({post}){constuser=useAuthUser();constisPostAuthor=post.author.userId!==user&&user.userId;返回isPostAuthor?:null;}此代码的问题是用户可能未定义。这就是为什么我们必须在尝试获取userId属性之前使用&&运算符以确保用户是一个对象。如果我想访问对象内的另一个对象,我必须包含另一个&&条件。这可能会导致代码复杂、难以理解。JavaScript可选链运算符(?.)允许我们在访问属性之前检查对象是否存在。使用它来简化上面的代码:exportdefaultfunctionEditButton({post}){constuser=useAuthUser();constisPostAuthor=post.author.userId!==user?.userId;返回isPostAuthor?:null;}这将防止任何类型错误并允许我们编写更清晰的条件逻辑。8、带括号的隐式返回在React应用中,可以使用function关键字的函数声明语法来编写组件,也可以使用箭头函数设置为变量。使用function关键字的组件必须在返回任何JSX之前使用return关键字。exportdefaultfunctionApp(){return();}通过将返回的代码包裹在一组括号中,可以隐式地从函数返回(不使用return关键字)行的JavaScript代码。对于使用箭头函数的组件,你不需要包含return关键字,你可以只用一组括号返回JSX。constApp=()();导出默认应用程序;另外,当使用.map()迭代一个元素列表时,你也可以跳过return关键字,只在内部函数体中使用一组括号返回JSX。函数PostList(){constposts=usePostData();returnposts.map(post())}9.使用空值合并运算符在JavaScript中,如果一个值为假(例如null、undefined、0,'',NaN),你可以使用||提供替代值的条件。例如,在需要显示给定产品价格的产品页面组件中,可以使用||有条件地显示价格或显示文本“产品不可用”。exportdefaultfunctionProductPage({product}){return(<>{product.price||"Productnotavailable"});}现有的有问题code,如果商品价格为0,则不显示商品价格,显示“商品不可用”。如果左侧为null或undefined,则需要更精确的运算符来仅返回表达式的右侧,否则不返回false。这时候就可以使用nullcoalescingoperator。当左操作数为null或undefined时,将返回右操作数。否则它将返回其左操作数:null??'打回来';//“回调”0??42;//0您可以使用null合并运算符来解决上面代码中的问题:"});}10、在React组件中使用三元表达式编写条件时,三个Meta表达式是必不可少的,常用于显示或隐藏组件和元素。当然,我们可以使用三元表达式和模板字符串来动态地为React元素添加或删除类名。导出默认函数App(){const{isDarkMode}=useDarkMode();return();}这个条件逻辑也可以应用于任何道具:导出默认函数App(){const{isMobile}=useDeviceDetect();return();}