by Khoa Pham
通过Khoa Pham
React and React Native are just frameworks, and they do not dictate how we should structure our projects. It all depends on your personal taste and the project you’re working on.
React和React Native只是框架,它们并不指示我们应该如何构建项目。 这完全取决于您的个人品味和您正在从事的项目。
In this post, we will go through how to structure a project and how to manage local assets. This of course is not written in stone, and you are free to apply only the pieces that suit you. Hope you learn something.
在本文中,我们将介绍如何构建项目以及如何管理本地资产。 当然,这不是一成不变的,您可以自由地仅应用适合您的作品。 希望你能学到一些东西。
For a project bootstrapped with react-native init
, we get only the basic structure.
对于使用react-native init
引导的项目,我们仅获得基本结构 。
There is the ios
folder for Xcode projects, the android
folder for Android projects, and an index.js
and an App.js
file for the React Native starting point.
Xcode项目有ios
文件夹,Android项目有android
文件夹,React Native起点有index.js
和App.js
文件。
ios/
android/
index.js
App.js
As someone who has worked with native on both Windows Phone, iOS and Android, I find that structuring a project all comes down to separating files by type or feature
作为曾经在Windows Phone,iOS和Android上使用Native的人,我发现构建项目的全部工作归结为按类型或功能分隔文件
Separating by type means that we organise files by their type. If it is a component, there are container and presentational files. If it is Redux, there are action, reducer, and store files. If it is view, there are JavaScript, HTML, and CSS files.
按类型分隔意味着我们按文件类型组织文件。 如果是组件,则有容器文件和演示文件。 如果是Redux,则有操作,Reducer和存储文件。 如果是视图,则包含JavaScript,HTML和CSS文件。
redux
actions
store
reducers
components
container
presentational
view
javascript
html
css
This way, we can see the type of each file, and easily run a script toward a certain file type. This is general for all projects, but it does not answer the question “what is this project about?” Is it news application? Is it a loyalty app? Is it about nutrition tracking?
这样,我们可以看到每个文件的类型,并轻松地针对特定文件类型运行脚本。 这对于所有项目都是通用的,但不能回答“此项目涉及什么?”的问题。 是新闻申请吗? 它是会员应用吗? 关于营养追踪吗?
Organising files by type is for a machine, not for a human. Many times we work on a feature, and finding files to fix in multiple directories is a hassle. It’s also a pain if we plan to make a framework out of our project, as files are spread across many places.
按类型组织文件是针对机器而不是人员。 很多时候,我们致力于一项功能,而要在多个目录中查找要修复的文件则很麻烦。 如果文件计划分布在许多地方,那么如果我们计划从项目中创建框架,这也是一个痛苦。
A more reasonable solution is to organise files by feature. Files related to a feature should be placed together. And test files should stay close to the source files. Check out this article to learn more.
一个更合理的解决方案是按功能组织文件。 与功能相关的文件应放置在一起。 测试文件应保持与源文件接近。 查看这篇文章以了解更多信息。
A feature can be related to login, sign up, onboarding, or a user’s profile. A feature can contain sub-features as long as they belong to the same flow. If we wanted to move the sub feature around, it would be easy, as all related files are already grouped together.
功能可以与登录,注册,注册或用户的个人资料相关。 特征可以包含子特征,只要它们属于同一流即可。 如果我们想移动子功能,这将很容易,因为所有相关文件已经分组在一起。
My typical project structure based on features looks like this:
我基于功能的典型项目结构如下所示:
index.js
App.js
ios/
android/
src
screens
login
LoginScreen.js
LoginNavigator.js
onboarding
OnboardingNavigator
welcome
WelcomeScreen.js
term
TermScreen.js
notification
NotificationScreen.js
main
MainNavigator.js
news
NewsScreen.js
profile
ProfileScreen.js
search
SearchScreen.js
library
package.json
components
ImageButton.js
RoundImage.js
utils
moveToBottom.js
safeArea.js
networking
API.js
Auth.js
res
package.json
strings.js
colors.js
palette.js
fonts.js
images.js
images
logo@2x.png
logo@3x.png
button@2x.png
button@3x.png
scripts
images.js
clear.js
Besides the traditional files App.js
and index.js
and the ios1
and android
folders, I put all the source files inside the src
folder. Inside src
I have res
for resources, library
for common files used across features, and screens
for a screen of content.
除了传统的App.js
和index.js
文件以及ios1
和android
文件夹之外,我ios1
所有源文件都放在src
文件夹中。 在src
内部,我拥有res
的资源,具有跨功能使用的通用文件的library
以及具有内容screens
的屏幕。
Since React Native is heavily dependent on tons of dependencies, I try to be pretty aware when adding more. In my project I use just react-navigation
for navigation. And I’m not a fan of redux
as it adds unneeded complexity. Only add a dependency when you really need it, otherwise you are just setting yourself up for more trouble than value.
由于React Native严重依赖大量的依赖关系,因此我在添加更多依赖时会非常清楚。 在我的项目中,我只使用react-navigation
进行导航。 而且我不喜欢redux
因为它增加了不必要的复杂性。 仅在确实需要时添加依赖项,否则,您设置自己的麻烦多于价值。
The thing I like about React is the components. A component is where we define view, style and behavior. React has inline style — it’s like using JavaScript to define script, HTML and CSS. This fits the feature approach we are aiming for. That’s why I don’t use styled-components. Since styles are just JavaScript objects, we can just share comment styles in library
.
我喜欢React的是组件。 组件是我们定义视图,样式和行为的地方。 React具有内联样式-就像使用JavaScript定义脚本,HTML和CSS。 这符合我们的目标特征方法。 这就是为什么我不使用样式组件 。 由于样式只是JavaScript对象,因此我们只能在library
共享注释样式。
I like Android a lot, so I name src
and res
to match its folder conventions.
我非常喜欢Android,因此我将src
和res
命名为匹配其文件夹约定。
react-native init
sets up babel for us. But for a typical JavaScript project, it’s good to organise files in the src
folder. In my electron.js
application IconGenerator, I put the source files inside the src
folder. This not only helps in terms of organising, but also helps babel transpile the entire folder at once. Just a command and I have the files in src
transpiled to dist
in a blink.
react-native init
为我们建立了babel。 但是对于典型JavaScript项目,最好将文件组织在src
文件夹中。 在我的electron.js
应用程序IconGenerator中 ,我将源文件放在src
文件夹中。 这不仅在组织方面有帮助,而且还可以帮助babel立即转换整个文件夹。 只需一个命令,我就可以将src
的文件瞬间转换为dist
。
babel ./src --out-dir ./dist --copy-files
React is based around components. Yup. There are container and presentational components, but we can compose components to build more complex components. They usually end in showing in the full screen. It is called Page
in Windows Phone, ViewController
in iOS and Activity
in Android. The React Native guide mentions screen very often as something that covers the entire space:
React是基于组件的。 对。 有容器和表示组件 ,但是我们可以组成组件以构建更复杂的组件。 它们通常以全屏显示结束。 在Windows Phone中称为Page
,在iOS中称为ViewController
,在Android中称为Activity
。 React Native指南经常提到屏幕,因为它覆盖了整个空间:
Mobile apps are rarely made up of a single screen. Managing the presentation of, and transition between, multiple screens is typically handled by what is known as a navigator.
移动应用很少由单个屏幕组成。 管理多个屏幕的显示以及它们之间的转换通常由导航器来处理。
Each screen is considered the entry point for each feature. You can rename the LoginScreen.js
to index.js
by leveraging the Node module feature:
每个屏幕均被视为每个功能的入口点。 您可以利用Node 模块功能将LoginScreen.js
重命名为index.js
:
Modules don’t have to be files. We can also create a
find-me
folder undernode_modules
and place anindex.js
file in there. The samerequire('find-me')
line will use that folder’sindex.js
file模块不必是文件。 我们还可以在
node_modules
下创建一个find-me
文件夹,并将index.js
文件放置在其中。 相同的require('find-me')
行将使用该文件夹的index.js
文件
So instead of import LoginScreen from './screens/LoginScreen'
, we can just do import LoginScreen from './screens'
.
因此,我们可以import LoginScreen from './screens/LoginScreen'
而不是import LoginScreen from './screens/LoginScreen'
import LoginScreen from './screens'
。
Using index.js
results in encapsulation and provides a public interface for the feature. This is all personal taste. I myself prefer explicit naming for a file, hence the name LoginScreen.js
.
使用index.js
进行封装并为该功能提供一个公共接口。 这都是个人品味。 我本人更喜欢为文件明确命名,因此命名为LoginScreen.js
。
react-navigation seems to be the most popular choice for handling navigation in a React Native app. For a feature like onboarding, there are probably many screens managed by a stack navigation, so there is OnboardingNavigator
.
react-navigation似乎是在React Native应用程序中处理导航的最流行选择。 对于诸如onboarding之类的功能,可能有许多由堆栈导航管理的屏幕,因此有OnboardingNavigator
。
You can think of Navigator as something that groups sub screens or features. Since we group by feature, it’s reasonable to place Navigator inside the feature folder. It basically looks like this:
您可以将Navigator看作是对子屏幕或功能进行分组的东西。 由于我们按功能分组,因此将Navigator放置在功能文件夹中是合理的。 基本上看起来像这样:
import { createStackNavigator } from 'react-navigation'
import Welcome from './Welcome'
import Term from './Term'
const routeConfig = {
Welcome: {
screen: Welcome
},
Term: {
screen: Term
}
}
const navigatorConfig = {
navigationOptions: {
header: null
}
}
export default OnboardingNavigator = createStackNavigator(routeConfig, navigatorConfig)
This is the most controversial part of structuring a project. If you don’t like the name library
, you can name it utilities
, common
, citadel
, whatever
…
这是构建项目中最有争议的部分。 如果您不喜欢名称library
,则可以将其命名为utilities
, common
, citadel
whatever
。
This is not meant for homeless files, but it is where we place common utilities and components that are used by many features. Things like atomic components, wrappers, quick fixes function, networking stuff, and login info are used a lot, and it’s hard to move them to a specific feature folder. Sometimes we just need to be practical and get the work done.
这并不意味着无家可归的文件,但是它是我们放置许多功能所使用的通用实用程序和组件的地方。 原子组件,包装器,快速修复功能,网络连接和登录信息等东西已被大量使用,并且很难将它们移动到特定的功能文件夹中。 有时我们只需要务实并完成工作即可。
In React Native, we often need to implement a button with an image background in many screens. Here is a simple one that stays inside library/components/ImageButton.js
. The components
folder is for reusable components, sometimes called atomic components. According to React naming conventions, the first letter should be uppercase.
在React Native中,我们经常需要在许多屏幕上实现带有图像背景的按钮。 这是一个简单的代码,位于library/components/ImageButton.js
。 components
文件夹用于可重用的组件,有时也称为原子组件 。 根据React命名约定,首字母应为大写。
import React from 'react'
import { TouchableOpacity, View, Image, Text, StyleSheet } from 'react-native'
import images from 'res/images'
import colors from 'res/colors'
export default class ImageButton extends React.Component {
render() {
return (
<TouchableOpacity style={styles.touchable} onPress={this.props.onPress}>
<View style={styles.view}>
<Text style={styles.text}>{this.props.title}</Text>
</View>
<Image
source={images.button}
style={styles.image} />
</TouchableOpacity>
)
}
}
const styles = StyleSheet.create({
view: {
position: 'absolute',
backgroundColor: 'transparent'
},
image: {
},
touchable: {
alignItems: 'center',
justifyContent: 'center'
},
text: {
color: colors.button,
fontSize: 18,
textAlign: 'center'
}
})
And if we want to place the button at the bottom, we use a utility function to prevent code duplication. Here is library/utils/moveToBottom.js
:
如果要将按钮放在底部,可以使用实用程序功能来防止代码重复。 这是library/utils/moveToBottom.js
:
import React from 'react'
import { View, StyleSheet } from 'react-native'
function moveToBottom(component) {
return (
<View style={styles.container}>
{component}
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'flex-end',
marginBottom: 36
}
})
export default moveToBottom
Then somewhere in the src/screens/onboarding/term/Term.js
, we can import by using relative paths:
然后在src/screens/onboarding/term/Term.js
,我们可以使用相对路径导入:
import moveToBottom from '../../../../library/utils/move'
import ImageButton from '../../../../library/components/ImageButton'
This is a big red flag in my eyes. It’s error prone, as we need to calculate how many ..
we need to perform. And if we move feature around, all of the paths need to be recalculated.
这是我眼中的一个大红旗。 这是很容易出错,因为我们需要计算有多少..
我们需要执行。 而且,如果我们移动特征,则所有路径都需要重新计算。
Since library
is meant to be used many places, it’s good to reference it as an absolute path. In JavaScript there are usually 1000 libraries to a single problem. A quick search on Google reveals tons of libraries to tackle this issue. But we don’t need another dependency as this is extremely easy to fix.
由于本应在许多地方使用library
,因此最好将其引用为绝对路径。 在JavaScript中,单个问题通常有1000个库。 在Google上进行的快速搜索显示,有许多图书馆可以解决此问题。 但是我们不需要另一个依赖,因为这非常容易解决。
The solution is to turn library
into a module
so node
can find it. Adding package.json
to any folder makes it into a Node module
. Add package.json
inside the library
folder with this simple content:
解决方案是将library
转换为module
以便node
可以找到它。 将package.json
添加到任何文件夹会使它成为Node module
。 使用以下简单内容将package.json
添加到library
文件夹中:
{
"name": "library",
"version": "0.0.1"
}
Now in Term.js
we can easily import things from library
because it is now a module
:
现在在Term.js
我们可以轻松地从library
导入内容,因为它现在是一个module
:
import React from 'react'
import { View, StyleSheet, Image, Text, Button } from 'react-native'
import strings from 'res/strings'
import palette from 'res/palette'
import images from 'res/images'
import ImageButton from 'library/components/ImageButton'
import moveToBottom from 'library/utils/moveToBottom'
export default class Term extends React.Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.heading}>{strings.onboarding.term.heading.toUpperCase()}</Text>
{
moveToBottom(
<ImageButton style={styles.button} title={strings.onboarding.term.button.toUpperCase()} />
)
}
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center'
},
heading: {...palette.heading, ...{
marginTop: 72
}}
})
You may wonder what res/colors
, res/strings
, res/images
and res/fonts
are in the above examples. Well, for front end projects, we usually have components and style them using fonts, localised strings, colors, images and styles. JavaScript is a very dynamic language, and it’s easy to use stringly types everywhere. We could have a bunch of #00B75D
color
across many files, or Fira
as a fontFamily
in many Text
components. This is error-prone and hard to refactor.
您可能想知道上面示例中的res/colors
, res/strings
, res/images
和res/fonts
是什么。 好吧,对于前端项目,我们通常有一些组件,并使用字体,本地化的字符串,颜色,图像和样式来对它们进行样式设置。 JavaScript是一种非常动态的语言,在任何地方都可以轻松使用字符串类型。 我们可以在许多文件中使用#00B75D
color
,也可以在许多Text
组件中使用Fira
作为fontFamily
。 这容易出错,并且难以重构。
Let’s encapsulate resource usage inside the res
folder with safer objects. They look like the examples below:
让我们使用更安全的对象将资源使用情况封装在res
文件夹中。 它们看起来像下面的示例:
res/colors
分辨率/颜色
const colors = {
title: '#00B75D',
text: '#0C222B',
button: '#036675'
}
export default colors
res/strings
分辨率/字符串
const strings = {
onboarding: {
welcome: {
heading: 'Welcome',
text1: "What you don't know is what you haven't learn",
text2: 'Visit my GitHub at https://github.com/onmyway133',
button: 'Log in'
},
term: {
heading: 'Terms and conditions',
button: 'Read'
}
}
}
export default strings
res/fonts
RES /字体
const fonts = {
title: 'Arial',
text: 'SanFrancisco',
code: 'Fira'
}
export default fonts
res/images
分辨率/图像
const images = {
button: require('./images/button.png'),
logo: require('./images/logo.png'),
placeholder: require('./images/placeholder.png')
}
export default images
Like library
, res
files can be access from anywhere, so let’s make it a module
. Add package.json
to the res
folder:
像library
一样, res
文件可以从任何地方访问,因此让我们将其作为一个module
。 将package.json
添加到res
文件夹:
{
"name": "res",
"version": "0.0.1"
}
so we can access resource files like normal modules:
因此我们可以像普通模块一样访问资源文件:
import strings from 'res/strings'
import palette from 'res/palette'
import images from 'res/images'
The design of the app should be consistent. Certain elements should have the same look and feel so they don’t confuse the user. For example, the heading Text
should use one color, font, and font size. The Image
component should use the same placeholder image. In React Native, we already use the name styles
with const styles = StyleSheet.create({})
so let’s use the name palette
.
应用程序的设计应保持一致。 某些元素应具有相同的外观,以免混淆用户。 例如,标题Text
应使用一种颜色,字体和字体大小。 Image
组件应使用相同的占位符图像。 在React Native中,我们已经将名称styles
与const styles = StyleSheet.create({})
使用,因此让我们使用名称palette
。
Below is my simple palette. It defines common styles for heading and Text
:
以下是我的简单调色板。 它定义了标题和Text
通用样式:
import colors from './colors'
const palette = {
heading: {
color: colors.title,
fontSize: 20,
textAlign: 'center'
},
text: {
color: colors.text,
fontSize: 17,
textAlign: 'center'
}
}
export default palette
And then we can use them in our screen:
然后我们可以在屏幕上使用它们:
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center'
},
heading: {...palette.heading, ...{
marginTop: 72
}}
})
Here we use the object spread operator to merge palette.heading
and our custom style object. This means that we use the styles from palette.heading
but also specify more properties.
在这里,我们使用对象散布运算符来合并palette.heading
和我们的自定义样式对象。 这意味着我们使用的是来自palette.heading
的样式,而且还指定了更多属性。
If we were to reskin the app for multiple brands, we could have multiple palettes. This is a really powerful pattern.
如果我们要为多个品牌重新设计应用程序,我们可能会有多个调色板。 这是一个非常强大的模式。
You can see that in /src/res/images.js
we have properties for each image in the src/res/images
folder:
您可以看到,在/src/res/images.js
我们在src/res/images
文件夹中具有每个图像的属性:
const images = {
button: require('./images/button.png'),
logo: require('./images/logo.png'),
placeholder: require('./images/placeholder.png')
}
export default images
This is tedious to do manually, and we have to update if there’s changes in image naming convention. Instead, we can add a script to generate the images.js
based on the images we have. Add a file at the root of the project /scripts/images.js
:
手动操作很麻烦,如果图像命名约定发生变化,我们必须进行更新。 相反,我们可以添加一个脚本以根据images.js
的图像生成images.js
。 在项目/scripts/images.js
的根目录添加一个文件:
const fs = require('fs')
const imageFileNames = () => {
const array = fs
.readdirSync('src/res/images')
.filter((file) => {
return file.endsWith('.png')
})
.map((file) => {
return file.replace('@2x.png', '').replace('@3x.png', '')
})
return Array.from(new Set(array))
}
const generate = () => {
let properties = imageFileNames()
.map((name) => {
return `${name}: require('./images/${name}.png')`
})
.join(',\n ')
const string = `const images = {
${properties}
}
export default images
`
fs.writeFileSync('src/res/images.js', string, 'utf8')
}
generate()
The cool thing about Node is that we have access to the fs
module, which is really good at file processing. Here we simply traverse through images, and update /src/res/images.js
accordingly.
关于Node的很酷的事情是我们可以访问fs
模块,它确实擅长文件处理。 在这里,我们只是遍历图像,并相应地更新/src/res/images.js
。
Whenever we add or change images, we can run:
每当我们添加或更改图像时,我们都可以运行:
node scripts/images.js
And we can also declare the script inside our main package.json
:
我们也可以在主package.json
声明脚本:
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest",
"lint": "eslint *.js **/*.js",
"images": "node scripts/images.js"
}
Now we can just run npm run images
and we get an up-to-date images.js
resource file.
现在我们可以运行npm run images
,我们得到了一个最新的images.js
资源文件。
React Native has some custom fonts that may be good enough for your projects. You can also use custom fonts.
React Native有一些自定义字体 ,可能对您的项目足够好。 您也可以使用自定义字体。
One thing to note is that Android uses the name of the font file, but iOS uses the full name. You can see the full name in Font Book app, or by inspecting in running app
需要注意的一件事是,Android使用字体文件的名称,而iOS使用全名。 您可以在Font Book应用程序中查看全名,也可以在运行的应用程序中查看
for (NSString* family in [UIFont familyNames]) {
NSLog(@"%@", family);
for (NSString* name in [UIFont fontNamesForFamilyName: family]) {
NSLog(@"Family name: %@", name);
}
}
For custom fonts to be registered in iOS, we need to declare UIAppFonts
in Info.plist
using the file name of the fonts, and for Android, the fonts need to be placed at app/src/main/assets/fonts
.
对于要在iOS中注册的自定义字体,我们需要使用字体的文件名在Info.plist
声明UIAppFonts
,对于Android,需要将字体放置在app/src/main/assets/fonts
。
It is good practice to name the font file the same as full name. React Native is said to dynamically load custom fonts, but in case you get “Unrecognized font family”, then simply add those fonts to target within Xcode.
优良作法是将字体文件命名为全名。 据说React Native可以动态加载自定义字体,但是如果您遇到“无法识别的字体系列”,只需将这些字体添加到Xcode中即可。
Doing this by hand takes time, luckily we have rnpm that can help. First add all the fonts inside res/fonts
folder. Then simply declare rnpm
in package.json
and run react-native link
. This should declare UIAppFonts
in iOS and move all the fonts into app/src/main/assets/fonts
for Android.
手动执行此操作需要花费时间,幸运的是我们有rnpm可以提供帮助。 首先将所有字体添加到res/fonts
文件夹中。 然后只需在package.json
声明rnpm
并运行react-native link
。 这应该在iOS中声明UIAppFonts
并将所有字体移动到Android的app/src/main/assets/fonts
中。
"rnpm": {
"assets": [
"./src/res/fonts/"
]
}
Accessing fonts by name is error prone, we can create a script similar to what we have done with images to generate a safer accession. Add fonts.js
to our scripts
folder
按名称访问字体容易出错,我们可以创建与图像相似的脚本来生成更安全的登录。 将fonts.js
添加到我们的scripts
文件夹中
const fs = require('fs')
const fontFileNames = () => {
const array = fs
.readdirSync('src/res/fonts')
.map((file) => {
return file.replace('.ttf', '')
})
return Array.from(new Set(array))
}
const generate = () => {
const properties = fontFileNames()
.map((name) => {
const key = name.replace(/\s/g, '')
return `${key}: '${name}'`
})
.join(',\n ')
const string = `const fonts = {
${properties}
}
export default fonts
`
fs.writeFileSync('src/res/fonts.js', string, 'utf8')
}
generate()
Now you can use custom font via R
namespace.
现在您可以通过R
名称空间使用自定义字体。
import R from 'res/R'
const styles = StyleSheet.create({
text: {
fontFamily: R.fonts.FireCodeNormal
}
})
This step depends on personal taste, but I find it more organised if we introduce the R namespace, just like how Android does for assets with the generated R class.
此步骤取决于个人喜好,但如果我们引入R名称空间,则我发现它会更加有条理,就像Android对带有生成的R类的资产所做的一样。
Once you externalize your app resources, you can access them using resource IDs that are generated in your project’s
R
class. This document shows you how to group your resources in your Android project and provide alternative resources for specific device configurations, and then access them from your app code or other XML files.外部化应用程序资源后,您可以使用在项目的
R
类中生成的资源ID来访问它们。 本文档向您展示如何在Android项目中对资源进行分组,以及为特定设备配置提供替代资源,然后从您的应用程序代码或其他XML文件访问它们。
This way, let’s make a file called R.js
in src/res
:
这样,让我们在src/res
创建一个名为R.js
的文件:
import strings from './strings'
import images from './images'
import colors from './colors'
import palette from './palette'
const R = {
strings,
images,
colors,
palette
}
export default R
And access it in the screen:
并在屏幕上访问它:
import R from 'res/R'
render() {
return (
<SafeAreaView style={styles.container}>
<Image
style={styles.logo}
source={R.images.logo} />
<Image
style={styles.image}
source={R.images.placeholder} />
<Text style={styles.title}>{R.strings.onboarding.welcome.title.toUpperCase()}</Text>
)
}
Replace strings
with R.strings
, colors
with R.colors
, and images
with R.images
. With the R annotation, it is clear that we are accessing static assets from the app bundle.
更换strings
用R.strings
, colors
与R.colors
,并且images
与R.images
。 使用R批注,很明显,我们正在从应用程序捆绑包中访问静态资产。
This also matches the Airbnb convention for singleton, as our R is now like a global constant.
这也符合Airbnb关于单例的约定 ,因为我们的R现在就像一个全局常数。
23.8 Use PascalCase when you export a constructor / class / singleton / function library / bare object.
23.8在导出构造函数/类/单例/函数库/裸对象时使用PascalCase。
const AirbnbStyleGuide = {
es6: {
},
}
export default AirbnbStyleGuide
In this post, I’ve shown you how I think you should structure folders and files in a React Native project. We’ve also learned how to manage resources and access them in a safer manner. I hope you’ve found it useful. Here are some more resources to explore further:
在这篇文章中,我向您展示了我如何应该在React Native项目中构造文件夹和文件。 我们还学习了如何管理资源并以更安全的方式访问它们。 希望您发现它有用。 这里有一些其他资源可供进一步探索:
Since you are here, you may enjoy my other articles
由于您在这里,因此您可能会喜欢我的其他文章
Position element at the bottom of the screen using Flexbox in React Native
If you like this post, consider visiting my other articles and apps ?