我发现React是相当令人愉快的前端技术。然而,有时我觉得我在一个有许多类似/重复元素的组件中重复着相同的老式模板。在这篇文章中,我将向你展示我有时喜欢使用定义组件的模式来简化React开发。
请注意,我将在这篇文章中使用React与Typescript,但这一切在没有类型定义的情况下也同样适用
一个例子。一个长形式的文本区域
假设我们正在开发某种调查应用程序,我们想问许多长形式的问题。我们知道我们需要大量的文本区域来问这些问题,并且我们想把答案存储在一个answers 对象中。
我们的调查将问到一堆不同的食物偏好问题。我们的例子问题将是。
- 告诉我们你的理想汉堡包
- 告诉我们你理想的比萨饼
- 你最喜欢的食物记忆是什么,为什么?
当然,我们可以把这些问题都写成自己的文本区。让我们看看这可能看起来如何。
import React, { useState } from 'react';
const initialAnswers = {
hamburger: '',
pizza: '',
memory: '',
};
function App() {
const [answers, setAnswers] = useState(initialAnswers);
return (
<form>
<div>
<label htmlFor="hamburger">Tell us about your ideal hamburger</label>
<br />
<textarea
id="hamburger"
value={answers.hamburger}
onChange={(e) => {
setAnswers({
...answers,
hamburger: e.target.value,
});
}}
/>
</div>
<div>
<label htmlFor="pizza">Tell us about your ideal pizza</label>
<br />
<textarea
id="pizza"
value={answers.pizza}
onChange={(e) => {
setAnswers({
...answers,
pizza: e.target.value,
});
}}
/>
</div>
<div>
<label htmlFor="memory">
What is your favorite food memory and why?
</label>
<br />
<textarea
id="memory"
value={answers.memory}
onChange={(e) => {
setAnswers({
...answers,
memory: e.target.value,
});
}}
/>
</div>
</form>
);
}
这很好,也很有效。但是如果我们有大约20个这样的问题呢?我们会在复制这些组件时感到很累。这就是模式方法真正发挥作用的地方。
使用模式来简化重复性的组件开发
与上面的方法相反,让我们做一些优化,使开发不那么乏味。首先,我们要做一个单一的变化处理程序,它可以处理我们表单中任何字段的变化。接下来,我们将创建一个对象数组,每个对象代表我们表单中的一个字段,我们将用它来生成我们所有的问题。
首先,让我们创建那个一致的onChange 处理器。
import React, { useState } from 'react';
const initialAnswers = {
hamburger: '',
pizza: '',
memory: '',
};
type Answers = typeof initialAnswers;
function App() {
const [answers, setAnswers] = useState(initialAnswers);
const onChange = <K extends keyof Answers>(key: K, value: Answers[K]) => {
setAnswers({
...answers,
[key]: value,
});
};
return <></>;
}
接下来,我们可以添加一个字段数组来进行迭代。
import React, { useState } from 'react';
const initialAnswers = {
hamburger: '',
pizza: '',
memory: '',
};
type Answers = typeof initialAnswers;
type Field = {
key: keyof Answers;
label: string;
};
const fields: Field[] = [
{ key: 'hamburger', label: 'Tell us about your ideal hamburger' },
{ key: 'pizza', label: 'Tell us about your ideal pizza' },
{ key: 'memory', label: 'What is your favorite food memory and why?' },
];
function App() {
const [answers, setAnswers] = useState(initialAnswers);
const onChange = <K extends keyof Answers>(key: K, value: Answers[K]) => {
setAnswers({
...answers,
[key]: value,
});
};
return <></>;
}
最后,我们可以对数组进行迭代,而不是键入每一个textarea 组件。
import React, { useState } from 'react';
const initialAnswers = {
hamburger: '',
pizza: '',
memory: '',
};
type Answers = typeof initialAnswers;
type Field = {
key: keyof Answers;
label: string;
};
const fields: Field[] = [
{ key: 'hamburger', label: 'Tell us about your ideal hamburger' },
{ key: 'pizza', label: 'Tell us about your ideal pizza' },
{ key: 'memory', label: 'What is your favorite food memory and why?' },
];
function App() {
const [answers, setAnswers] = useState(initialAnswers);
const onChange = <K extends keyof Answers>(key: K, value: Answers[K]) => {
setAnswers({
...answers,
[key]: value,
});
};
return (
<form>
{fields.map(({ key, label }) => (
<div key={key}>
<label htmlFor={key}>{label}</label>
<br />
<textarea
id={key}
value={answers[key]}
onChange={(e) => {
onChange(key, e.target.value);
}}
/>
</div>
))}
</form>
);
}
export default App;
就这样,我们拥有了它!现在我们可以根据需要在我们的数组中添加任意多的字段,新的文本区将被自动地添加到应用程序中。