通过这 5 个技巧提升你的 React 技能
由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!
概括
我们将分析一段我们都见过(或迟早会遇到)的 JavaScript 代码。我会尝试对其进行一些改进,并解释我改进的原因。希望这对您有所帮助!
犯罪现场
function Othercomponent({ children, props }) {
return <div {...props}>{children}</div>;
}
const MyComponent = ({
id,
text,
style,
extraProps,
oneList,
containerOfThings,
aType,
}) => {
const whichString = aType == "SomeString" ? "aString" : "bString";
const whichNumber = aType == "SomeString" ? 123 : 321;
const extraThing = "Hey! I am a string";
if (containerOfThings && oneList && oneList.length > 1) {
return (
<ul>
<Othercomponent
whichString={whichString}
whichNumber={whichNumber}
id={id}
style={style}
extraProps={extraProps}
alt={oneList[0]}
extraThing={extraThing}
>
{text}
</Othercomponent>
<Othercomponent
whichString={whichString}
whichNumber={whichNumber}
id={id}
style={style}
extraProps={extraProps}
alt={oneList[1]}
extraThing={extraThing}
>
{text}
</Othercomponent>
<Othercomponent
whichString={whichString}
whichNumber={whichNumber}
id={id}
style={style}
extraProps={extraProps}
alt={oneList[2]}
extraThing={extraThing}
>
{text}
</Othercomponent>
</ul>
);
} else {
return (
<Othercomponent
whichString={whichString}
whichNumber={whichNumber}
id={id}
style={style}
extraProps={extraProps}
extraThing={extraThing}
alt={text}
>
{text}
</Othercomponent>
);
}
return <></>;
};
const MyApp = (props) => (
<MyComponent id={123} aType={"SomeString"} text="some content" {...props} />
);
好吧……请耐心听我说。我知道它现在看起来很糟糕。让我们一步一步地尝试改进它。
第一,保持一致性
在第一个组件中,我们使用 `@Component`而不是 PascalCase 命名<Othercomponent/>法来声明组件。而在第二个组件中,我们使用了箭头函数和 PascalCase 命名法。保持代码库的一致性非常重要,这样在创建另一个组件时,你和你的队友就不必再质疑组件的正确定义方式了。如果代码库保持一致,你的其他开发人员就能更好地了解当前状态和遵循的规则,从而避免在现有代码的基础上编写新代码时每一步都反复质疑。function XXXXX() { /* ... */ }<MyComponent/>
从:
function Othercomponent({ children, props }) {
return <div {...props}>{children}</div>;
}
到:
const OtherComponent = ({ children, props }) => {
return <div {...props}>{children}</div>;
};
结果:
const OtherComponent = ({ children, props }) => {
return <div {...props}>{children}</div>;
};
const MyComponent = ({
id,
text,
style,
extraProps,
oneList,
containerOfThings,
aType,
}) => {
const whichString = aType == "SomeString" ? "aString" : "bString";
const whichNumber = aType == "SomeString" ? 123 : 321;
const extraThing = "Hey! I am a string";
if (containerOfThings && oneList && oneList.length > 1) {
return (
<ul>
<OtherComponent
whichString={whichString}
whichNumber={whichNumber}
id={id}
style={style}
extraProps={extraProps}
alt={oneList[0]}
extraThing={extraThing}
>
{text}
</OtherComponent>
<OtherComponent
whichString={whichString}
whichNumber={whichNumber}
id={id}
style={style}
extraProps={extraProps}
alt={oneList[1]}
extraThing={extraThing}
>
{text}
</OtherComponent>
<OtherComponent
whichString={whichString}
whichNumber={whichNumber}
id={id}
style={style}
extraProps={extraProps}
alt={oneList[2]}
extraThing={extraThing}
>
{text}
</OtherComponent>
</ul>
);
} else {
return (
<OtherComponent
whichString={whichString}
whichNumber={whichNumber}
id={id}
style={style}
extraProps={extraProps}
extraThing={extraThing}
alt={text}
>
{text}
</OtherComponent>
);
}
return <></>;
};
const MyApp = (props) => (
<MyComponent id={123} aType={"SomeString"} text="some content" {...props} />
);
#2 利用语言/框架特性
最近我在为前端工程师进行代码审查时,发现一个非常普遍的现象:我们不再熟悉框架的功能或语言提供的语法糖。
儿童作为道具
我们知道,在 React 组件内部编写的所有内容都是子组件,而子组件会作为 props 传递(你可以直接在组件内部传递,也可以通过children={'my child'}prop 传递)。因此,我们在实现组件时可以充分利用这一点。
无退货声明
我们可以利用 JavaScript 的单行函数特性,这些函数不需要任何return关键字。请充分利用这些由优秀开发者们贡献的功能!https://github.com/tc39/proposals
从:
const OtherComponent = (props) => {
return <div {...props} />;
};
const MyComponent = ({
id,
text,
style,
extraProps,
oneList,
containerOfThings,
aType,
}) => {
// ..
<OtherComponent
whichString={whichString}
whichNumber={whichNumber}
id={id}
style={style}
extraProps={extraProps}
alt={oneList[0]}
extraThing={extraThing}
>
{text}
</OtherComponent>
// ...
到:
const OtherComponent = (props) => <div {...props} />;
const MyComponent = ({
id,
children,
style,
extraProps,
oneList,
containerOfThings,
aType,
}) => {
// ...
<OtherComponent
whichString={whichString}
whichNumber={whichNumber}
id={id}
style={style}
extraProps={extraProps}
alt={oneList[0]}
extraThing={extraThing}
>
{children}
</OtherComponent>
// ...
结果:
const OtherComponent = (props) => <div {...props} />;
const MyComponent = ({
id,
children,
style,
extraProps,
oneList,
containerOfThings,
aType,
}) => {
const whichString = aType == "SomeString" ? "aString" : "bString";
const whichNumber = aType == "SomeString" ? 123 : 321;
const extraThing = "Hey! I am a string";
if (containerOfThings && oneList && oneList.length > 1) {
return (
<ul>
<OtherComponent
whichString={whichString}
whichNumber={whichNumber}
id={id}
style={style}
extraProps={extraProps}
alt={oneList[0]}
extraThing={extraThing}
>
{children}
</OtherComponent>
<OtherComponent
whichString={whichString}
whichNumber={whichNumber}
id={id}
style={style}
extraProps={extraProps}
alt={oneList[1]}
extraThing={extraThing}
>
{children}
</OtherComponent>
<OtherComponent
whichString={whichString}
whichNumber={whichNumber}
id={id}
style={style}
extraProps={extraProps}
alt={oneList[2]}
extraThing={extraThing}
>
{children}
</OtherComponent>
</ul>
);
} else {
return (
<OtherComponent
whichString={whichString}
whichNumber={whichNumber}
id={id}
style={style}
extraProps={extraProps}
extraThing={extraThing}
alt={children}
>
{children}
</OtherComponent>
);
}
return <></>;
};
const MyApp = (props) => (
<MyComponent id={123} aType={"SomeString"} {...props}>
some content
</MyComponent>
);
#3 无缘无故地直白
有些人喜欢主张我们应该始终显式地定义所有属性,每个组件都应该解析所有属性。我理解这种做法在某些情况下是可取的,但在大多数情况下,它只会增加代码的冗余。如果你确实需要这样做,请考虑迁移到 TypeScript(或者如果你只是想编写更好的 JavaScript 代码)。在我们的示例中,我们可以隐式地定义很多东西,因为我们解析了一些我们从未用到且并不关心的变量。
从:
// ...
const MyComponent = ({
id,
children,
style,
extraProps,
oneList,
containerOfThings,
aType,
}) => {
// ...
<OtherComponent
whichString={whichString}
whichNumber={whichNumber}
id={id}
style={style}
extraProps={extraProps}
alt={oneList[0]}
extraThing={extraThing}
>
{children}
</OtherComponent>
到:
// ...
const MyComponent = ({ oneList, containerOfThings, aType, ...props }) => {
// ...
<OtherComponent
whichString={whichString}
whichNumber={whichNumber}
alt={oneList[0]}
extraThing={extraThing}
{...props}
/>
结果:
const OtherComponent = (props) => <div {...props} />;
const MyComponent = ({ oneList, containerOfThings, aType, ...props }) => {
const whichString = aType == "SomeString" ? "aString" : "bString";
const whichNumber = aType == "SomeString" ? 123 : 321;
const extraThing = "Hey! I am a string";
if (containerOfThings && oneList && oneList.length > 1) {
return (
<ul>
<OtherComponent
whichString={whichString}
whichNumber={whichNumber}
alt={oneList[0]}
extraThing={extraThing}
{...props}
/>
<OtherComponent
whichString={whichString}
whichNumber={whichNumber}
alt={oneList[1]}
extraThing={extraThing}
{...props}
/>
<OtherComponent
whichString={whichString}
whichNumber={whichNumber}
alt={oneList[2]}
extraThing={extraThing}
{...props}
/>
</ul>
);
} else {
return (
<OtherComponent
whichString={whichString}
whichNumber={whichNumber}
alt={oneList[0]}
extraThing={extraThing}
{...props}
/>
);
}
return <></>;
};
const MyApp = (props) => (
<MyComponent
id={123}
aType={"SomeString"}
{...props}
containerOfThings={true}
oneList={["alt1", "alt2", "alt3"]}
>
some content
</MyComponent>
);
#4 减少逻辑分支/降低代码出错率
我们都喜欢三元运算符和不必要的变量,我懂。我也掉进过这个陷阱,为了让某个功能正常运行,就觉得用if三元运算符检查或赋值是解决办法。但大多数时候并非如此。这样做只会增加你实现代码完整/良好测试覆盖率所需的时间。
当我们偶尔添加这些逻辑分支时,我们会犯一些愚蠢的错误,例如编写无法访问的代码,或者使我们的代码变得比应该的更复杂。
移除三元运算符
减少三元条件语句逻辑分支的一个巧妙技巧是使用映射(也可以称为哈希/对象)。你可以把它们看作是配置辅助工具。😇
从:
// ...
const whichString = aType == "SomeString" ? "aString" : "bString";
const whichNumber = aType == "SomeString" ? 123 : 321;
// ...
<OtherComponent
whichString={whichString}
whichNumber={whichNumber}
alt={oneList[0]}
extraThing={extraThing}
{...props}
/>;
// ...
到:
// ...
const valuesMap = {
SomeString: { str: "aString", num: 123 },
OtherString: { str: "bString", num: 321 },
};
// ...
<OtherComponent
whichString={valuesMap[aType].str}
whichNumber={valuesMap[aType].num}
alt={oneList[0]}
extraThing={extraThing}
{...props}
/>;
// ...
结果:
const OtherComponent = (props) => <div {...props} />;
const MyComponent = ({ oneList, containerOfThings, aType, ...props }) => {
const valuesMap = {
SomeString: { str: "aString", num: 123 },
OtherString: { str: "bString", num: 321 },
};
const extraThing = "Hey! I am a string";
if (containerOfThings && oneList && oneList.length > 1) {
return (
<ul>
<OtherComponent
whichString={valuesMap[aType].str}
whichNumber={valuesMap[aType].num}
alt={oneList[0]}
extraThing={extraThing}
{...props}
/>
<OtherComponent
whichString={valuesMap[aType].str}
whichNumber={valuesMap[aType].num}
alt={oneList[1]}
extraThing={extraThing}
{...props}
/>
<OtherComponent
whichString={valuesMap[aType].str}
whichNumber={valuesMap[aType].num}
alt={oneList[2]}
extraThing={extraThing}
{...props}
/>
</ul>
);
} else {
return (
<OtherComponent
whichString={valuesMap[aType].str}
whichNumber={valuesMap[aType].num}
alt={oneList[0]}
extraThing={extraThing}
{...props}
/>
);
}
return <></>;
};
const MyApp = (props) => (
<MyComponent
id={123}
aType={"SomeString"}
{...props}
containerOfThings={true}
oneList={["alt1", "alt2", "alt3"]}
>
some content
</MyComponent>
);
简化操作,移除条件语句
函数式编程(FP)范式出现并再次流行起来已经好几年了。因此,现在是时候停止使用函数ifs式编程,并提高代码质量了。
在这个例子中,我们可以看到存在不必要的返回值,这个例子虽然很愚蠢或显而易见,但我保证你肯定读过或正在读过一些带有无用条件的代码。
如果我们能找到办法让所有场景都使用相同的 HTML 结构,你的代码就会变得极其简洁。如果你还没找到明确的实现方法,可能需要提升一下你的 CSS 技能。
结果:
const OtherComponent = (props) => <div {...props} />;
const MyComponent = ({ oneList = [], aType, ...props }) => {
const valuesMap = {
SomeString: { str: "aString", num: 123 },
OtherString: { str: "bString", num: 321 },
};
const extraThing = "Hey! I am a string";
return (
<ul>
{oneList.map((item) => (
<OtherComponent
whichString={valuesMap[aType].str}
whichNumber={valuesMap[aType].num}
alt={item}
key={item}
extraThing={extraThing}
{...props}
/>
))}
</ul>
);
};
const MyApp = (props) => (
<MyComponent
id={123}
aType={"SomeString"}
{...props}
containerOfThings={true}
oneList={["alt1", "alt2", "alt3"]}
>
some content
</MyComponent>
);
#5 React 应用中的常量
我给这篇文章的最后一个建议是:检查你的常量!
务必将它们放在 React 组件之外,这样每次调用组件时就不需要重新声明它们。此外,为 props 设置默认值,可以让所有人知道组件的默认行为,从而节省时间。
结果:
const STRING_TYPES = { SomeString: "SomeString", OtherString: "OtherString" };
const valuesMap = {
SomeString: { whichString: "aString", whichNumber: 123 },
OtherString: { whichString: "bString", whichNumber: 321 },
};
const extraThing = "Hey! I am a string";
const OtherComponent = (props) => <div {...props} />;
const MyComponent = ({
aType = STRING_TYPES.SomeString,
oneList = [],
...props
}) => (
<ul>
{oneList.map((item) => (
<OtherComponent
alt={item}
key={item}
extraThing={extraThing}
{...valuesMap[aType]}
{...props}
/>
))}
</ul>
);
const MyApp = (props) => (
<MyComponent
id={123}
aType={STRING_TYPES.SomeString}
containerOfThings={true}
oneList={["alt1", "alt2", "alt3"]}
{...props}
>
some content
</MyComponent>
);
结束了!
希望这对你们有帮助!
祝好,注意安全!
文章来源:https://dev.to/grekz/improve-your-react-skills-with-these-5-tips-2c65