我正在和我的团队建立一个React项目,将使用mobX作为状态管理器,外加TypeScript.

我在React项目的shell 和命名模式中看到了一种常见模式:

  1. 非react 文件夹和文件:camelCasekebab-case
  2. react (components文件夹内):PascalCase

react中是否有文件夹/文件命名的正式约定?如果没有,是否有此模式所依据的样式指南?或者这是为什么大多数时候都会用到的原因?

推荐答案

再加上我的两分钱.正如其他人所说,文件 struct 是非编译的.然而,组件命名并不重要.它们应该是PascalCase,以便React知道您使用的是functionclass还是HTMLelement†.

例如:

class input extends Component {...}

Bad! 为什么?因为React不知道您是在try 使用input元素还是基于类的组件.

这就是为什么你会看到PascalCase组件:

class Input extends Component {...}

†有一个例外,您可以使用dot notation.例如,如果您有多个导出,并将它们全部作为fields导入,则可以执行以下操作:

component/fields/index.js

import React, { Component } from 'react';

export class input extends Component {
  state = { value: "" };

  handleChange = ({ target: { value } }) => {
    this.setState({ value });
  };

  render = () => (
    <input type="text" value={this.state.value} onChange={this.handleChange} />
  );
}

export class textarea extends Component {
  state = { value: "" };

  handleChange = ({ target: { value } }) => {
    this.setState({ value });
  };

  render = () => (
    <textarea
      type="text"
      value={this.state.value}
      onChange={this.handleChange}
    />
  );
}

components/App/index.js

import React, { Fragment } from 'react';
import * as fields from "../fields";

const App = () => (
  <Fragment>
     <fields.input />
     <fields.textarea />
   <Fragment>
);

export default App;

一般来说,我总共避免dot notation次.它感觉很笨拙,可能会让其他不知道fields是如何构造的开发人员感到困惑.另外,我不喜欢在一个文件中堆叠多个组件,然后将它们作为一堆导入.此外,该文件可能会变得非常大,导航和调试起来也会非常麻烦(下文将对此进行详细介绍).


也就是说,为了保持 struct 简单,我喜欢将主目录保持小写:

├── dist // compiled application files to be served
|   ├── css
|   |   ├── main.[contenthash:8].css
|   |   └── main.[contenthash:8].css.map
|   ├── js
|   |   ├── main.[hash].js // depending on app size, this may contain multiple js files for code splitting
|   |   └── main.[hash].js.map
|   ├── media
|   |   └── [hash].[ext] // static assets like fonts and images
|   └── favicon.ico
|   └── index.html
|
├── config // supporting "webpackdevserver" configuration files
|   ├── devServer.js
|   ├── envs.js
|   ├── optimization.js
|   ├── output.js
|   ├── paths.js
|   ├── plugins.js
|   └── rules.js
|
├── public
|   ├── favicon.ico
|   └── index.html
|
├── src
|   ├── actions // redux actions
|   ├── components // stateful and stateless reusable components that just display "stuff" -- stateful components change and manipulate the UI
|   ├── containers // stateful components that utilize the reusable "components" to CRUD data and/or are connected to redux
|   ├── images
|   ├── pages // utilize components/containers to display something when visiting a "/route"
|   ├── reducers // redux reducers
|   ├── root // aka "<App />" that combines "routes", redux and other top-level supporting files into one place
|   ├── routes // assigns "pages" to a "/route"
|   ├── styles // shared and/or global styles used by all "components"
|   ├── types // redux types
|   ├── utils // supporting app files: like test setup, custom polyfills, axios configurations, ...etc
|   └── index.js // a simple file that "ReactDOM.render"s the "App"
|
├── server.js // express setup to serve the "dist" folder
└── webpack.config.js

然后在component文件夹中,我将使用PascalCase组件来表示如下内容:

└── components
    └── Input
        ├── __tests__
        |   └── Input.test.js // jest unit tests for "index.js"
        ├── index.js // all required code/styles to be exported
        └── styles.scss // styles required by "index.js"

Why this structure?

  • 可重复使用的组件,可随时随地使用.
  • Input相关的所有内容都包含在此文件夹中.
  • Webpack已设置为自动导入index.js个文件,因此无需遍历大量嵌套文件即可轻松导入:import Input from 'components/Input';(此外,无需指定要使用的确切js文件,因为"index.js"包含所有必需的代码).

Drawbacks:

  • 你会有很多小文件夹.
  • 编译错误都会包含index.js个术语,所以一开始可能会有点混淆"index.js"失败了什么.

我过go 的另一种方法是:

└── components
    ├── input // lowercase name to delineate it's a "pure" function -- the actual function will be a PascalCased "Input"
    |   ├── input.test.js // jest unit tests for "input.js"
    |   ├── input.js // all required code/styles to be exported
    |   └── styles.scss // styles required by "input.js"
    |
    └── Sidebar // PascalCase because it's a "class"
        ├── Sidebar.test.js // jest unit tests for "Sidebar.js"
        ├── Sidebar.js // all required code/styles to be exported
        └── styles.scss // styles required by "Sidebar.js"

Why this structure?

  • 可重复使用的组件,可随时随地使用.
  • Input相关的所有内容都包含在此文件夹中.
  • 根据主文件夹的不同,它描述了组件是function还是class.
  • 当发生编译错误时,我确切地知道是哪个文件导致了错误.

Drawbacks:

  • 你会有很多小文件夹.
  • 有时,组件可能会从有状态更改为无状态(反之亦然),因此如果您严格遵守此命名模式,则必须更新主文件夹以反映更改,这意味着您还需要更新使用此组件的任何其他文件的路径.
  • 导入可能看起来有点多余和冗长:import Input from 'components/input/input.js';

其他一般准则:

  • Avoid default exporting an anonymous function:

默认导出的匿名函数示例:

export default () => (
  <p>Anonymous Function</p>
);

为什么?因为在测试时,该功能将在Enzyme 中显示为:

<_default />

当一个组件中有多个匿名函数时,哪个是哪个!?

<_default />
<_default />
<_default />
  • Avoid lengthy files (150 lines or less) as it becomes a pain to read/understand and even more of a pain to debug.

通常情况下,我发现如果进行适当优化,most个组件将落在most行左右.最糟糕的情况是我必须创建小的子组件来补充主组件.但是更容易阅读和调试.

更容易阅读的内容:

Example #1(34行,带有补充的子组件)

Example #2(318行)

例#1模仿看书.多页,当粘在一起创造一个易于阅读的体验.而例子#2读起来像一英里长的卷轴,很容易迷路!

  • Stylesheets can be snake-case or camelCase.

这可能会让人困惑,但这完全取决于你如何应用风格.如果只是像这样导入样式:

import "./styles.css";

然后可以使用snake case:

<input className="snake-case" type="text" value="" onChange={this.handleChange} />

但是,如果使用css modules,则需要使用camelCase:

import { camelCaseClassName } from "./styles.css";

为什么?因为Bundle 包(比如Webpack)不支持蛇壳导入:

<input className={camelCaseClassName} type="text" value="" onChange={this.handleChange} />

结论:创建文件夹 struct 有很多方法,其中包括一些技巧和技巧,以保持逻辑流.只需 Select 一个最适合你且不会干扰你身边工作的人!

In other words, K.I.S.S === "Keep it simple, silly!"

Reactjs相关问答推荐

如何在Pivot模式下自定义标题?

CreateBrowserRouter将props 传递给父组件以验证权限

使用Reaction钩子窗体验证可选字段

NextJS如何正确保存添加到购物车中的产品会话

react ';S使用状态不设置新状态

Redux工具包-useSelector如何通过Reducer引用InitialState?

无法在REACTION TANSTACK查询中传递参数

React,当我调用handleSubmit()函数时,我正在将application/json和multiform/data中的数据发送到后端,但student_image中没有数据:null

如何修复ReferenceError:在构建过程中未定义导航器

React useEffect 依赖项

React-dom 的钩子调用无效.我能做些什么?

未捕获的运行时错误:对象作为 React 子项无效

在 CrafterCMS Studio 中拖动字段

Material UI v5.11 - Prop sx 在响应式中写了两次

null 不是对象(判断RNSound.IsAndroid)

更新和删除功能不工作 Asp.net MVC React

Storybook - 无法解析generated-stories-entry.cjs/字段browser不包含有效的别名配置

NextJs - 如何从站点 map 生成器中删除重复的 URL?

如何将本地视频文件上传到 Google Cloud

由于另一个子组件,如何在react 中渲染另一个子组件