我正在开发一种动态表单,人们可以在其中创建调查问题。
主窗体允许添加问题,每个问题可以添加1:N条件和答案。
主模板如下所示:
import React, { useState } from "react";
import Question from 'components/templates/question';
import { Button, Form } from 'react-bootstrap';
const Templates = () => {
const [questions, setQuestions] = useState([Question()]);
const increase = () => {
setQuestions([...questions, Question()]);
};
return (
<form>
{questions.map((component, index) => (
<React.Fragment key={index}>
{ component }
</React.Fragment>
))}
<Button variant='success' onClick={increase}> + </Button>
</form>
);
};
包含可递增、可重复条件的问题如下所示:
import React, { useState } from "react";
import { Button, Card, Form } from 'react-bootstrap';
import Condition from './condition';
const Question = () => {
const [conditions, setConditions] = useState([Condition()]);
const increaseC = () => {
setConditions([...conditions, Condition()]);
};
return (
<Card className="mb-4">
<Card.Body>
<Form.Group className="mb-3" controlId="questionTitle">
<Form.Label>Question Title</Form.Label>
<Form.Control type="text" placeholder="What is a simple name for this data point?" />
</Form.Group>
<Form.Group className="mb-3" controlId="questionDescription">
<Form.Label>Question Description</Form.Label>
<Form.Control type="text" placeholder="What are you looking for?" />
</Form.Group>
<h5 class="card-title">Conditions</h5>
<h6 class="card-subtitle text-muted">Are there conditions for when this text is displayed?</h6>
{conditions.map((component, index) => (
<React.Fragment key={index}>
{ component }
</React.Fragment>
))}
<br />
<Button variant='outline-success' size="sm" onClick={increaseC}>+</Button>
</Card.Body>
</Card>
);
}
export default Question;
正如你所想,这是行不通的。我见过在组件之间传递参数,但我一生都无法弄清楚如何拥有映射组件集合的多个状态。
您可以采取多种方法。主要思想是存储条件数据而不是组件本身。您应该使您的
<Condition />
成为受控组件,它将数据作为道具,并提供 onChange
回调,以在编辑后更新条件。
interface ConditionData {
// condition-related data
}
// store a list of conditions' data
const [conditions, setConditions] = useState<ConditionData>([]);
const increaseC = () => {
setConditions([...conditions, { ...initialConditionData }]);
};
const onConditionChange = useCallback((data: ConditionData, index: number) => {
// Update condition that changed on the given index
setConditions(conditions =>
conditions.map((condition, conditionIndex) =>
conditionIndex === index ? data : condition
)
);
}, []);
return (
...
{conditions.map((data, index) => (
<Condition
key={index}
data={data}
onChange={(data) => onConditionChange(data, index)}
/>
))}
...
)
理想情况下,您应该为新条件生成唯一的 ID,以便在删除条件后,未更改条件的键不会更改。这是对上面代码的简单修改。
interface ConditionData {
id: number;
// condition-related data
}
function* createConditionGenerator() {
let id = 0;
while (true) {
yield { ...initialConditionData, id }
id++;
}
}
const generateNewCondition = createConditionGenerator();
const [conditions, setConditions] = useState<ConditionData>([generateNewCondition.next().value]);
const increaseC = () => {
setConditions([...conditions, ]);
};
const onConditionChange = useCallback((data: ConditionData) => {
// Update condition that changed on the given index
setConditions(conditions =>
conditions.map((condition) =>
condition.id === data.id ? data : condition
)
);
}, []);
return (
...
{conditions.map((data) => (
<Condition
key={data.id}
data={data}
onChange={onConditionChange}
/>
))}
...
)