我正在用下面给出的代码编写组件,渲染后的样子如下:
我已经使用antd组件来渲染字段。我面临的问题是我既无法从选择框中进行选择,也无法在输入字段中进行书写,如下所示。我有一种感觉,我在从key
获得的render方法中不恰当地将React的mocFields
用于getMOCField
。
import React, { Component } from "react";
import { Button, Icon, Select, Form, Input } from "antd";
const FormItem = Form.Item;
const Option = Select.Option;
import { FormComponentProps } from "antd/lib/form/Form";
type state = {
mocFields: JSX.Element[]
};
export class MOC extends Component<FormComponentProps, state> {
constructor(props) {
super(props);
this.state = {
mocFields: []
};
this.addMOCField = this.addMOCField.bind(this);
this.removeMOCField = this.removeMOCField.bind(this);
}
componentDidMount() {}
componentWillReceiveProps(nextProps) {}
removeMOCField(key, event: React.MouseEvent<HTMLElement>) {
event.preventDefault();
const { mocFields } = this.state;
mocFields.splice(key, 1);
this.setState({
mocFields
});
}
getMOCFieldFooter() {
return (
<div className="d-flex justify-content-between small">
<div className="inline-block">
<Button
type="primary"
shape="circle"
icon="plus"
ghost
size="small"
className="d-font mr-1"
onClick={this.addMOCField}
/>
<div
className="text-primary pointer d-font inline-block letter-spacing-1"
onClick={this.addMOCField}
>
Add another
</div>
<div className="d-font inline-block letter-spacing-1">or </div>
<div className="text-primary pointer d-font inline-block letter-spacing-1">
Create a new MOC
</div>
</div>
</div>
);
}
getMOCField(key) {
const { getFieldDecorator } = this.props.form;
return (
<div className="d-flex justify-content-between">
<div className="inline-block">
<FormItem label="Select MOC">
{getFieldDecorator(`selected_moc[${key}]`, {
rules: [
{
required: true,
message: "Please select moc"
}
]
})(
<Select>
<Option value={"A"}>A</Option>
<Option value={"B"}>B</Option>
</Select>
)}
</FormItem>
</div>
<div className="inline-block">
<FormItem label="Recovery (%)">
{getFieldDecorator(`recovery_percentage[${key}]`, {
rules: [
{
required: true,
message: "Please input the recovery percentage"
}
]
})(<Input type="number" step="0.000001" />)}
</FormItem>
</div>
<div className="inline-block pointer">
<span>
<Icon type="close" onClick={this.removeMOCField.bind(this, key)} />
</span>
</div>
</div>
);
}
addMOCField(event: React.MouseEvent<HTMLElement>) {
event.preventDefault();
const { mocFields } = this.state;
const MOCField = this.getMOCField(mocFields.length);
mocFields.push(MOCField);
this.setState({
mocFields
});
}
getAddMOCButton() {
return (
<div className="d-flex w-100 mt-3">
<Button
type="primary"
ghost
className="w-100"
onClick={this.addMOCField}
>
<Icon type="plus-circle" />
Add MOC
</Button>
</div>
);
}
render() {
const { mocFields } = this.state;
const mocButton = this.getAddMOCButton();
const toRender =
mocFields.length > 0 ? (
<div className="w-100 p-2 gray-background br-25">
{mocFields.map((f, index) => (
<div key={index}>{f}</div>
))}
{this.getMOCFieldFooter()}
</div>
) : (
mocButton
);
return toRender;
}
}
这可能是什么原因?我做错了什么?目前,上述组件的呈现方式如下:
mocFields
中的字段数为零,那么将显示一个用于添加新字段的按钮。mocField
会被填充选择框和输入字段,如上所示。 div
的键是在render方法期间确定的。答案 0 :(得分:1)
似乎侦听器一旦存储在数组中就无法工作。我尝试在getMOCField
函数中内联对render
的调用,并且它可以正常工作。这是我为了使其工作而进行的更改:
class MOC extends Component {
// ...
addMOCField(event) {
event.preventDefault();
const { mocFields } = this.state;
// We only keep inside the state an array of number
// each one of them represent a section of fields.
const lastFieldId = mocFields[mocFields.length - 1] || 0;
const nextFieldId = lastFieldId + 1;
this.setState({
mocFields: mocFields.concat(nextFieldId),
});
}
removeMOCField(key, event) {
event.preventDefault();
this.setState(prevState => ({
mocFields: prevState.mocFields.filter(field => field !== key)
}));
}
render() {
const { mocFields } = this.state;
const mocButton = this.getAddMOCButton();
const toRender =
mocFields.length > 0 ? (
<div className="w-100 p-2 gray-background br-25">
{/* {mocFields.map((f, index) => (
<div key={index}>{f}</div>
))} */}
{mocFields.map(fieldIndex => (
<div key={fieldIndex}>{this.getMOCField(fieldIndex)}</div>
))}
{this.getMOCFieldFooter()}
</div>
) : (
mocButton
);
return toRender;
}
}