我正在尝试将EditableTabGroup
转换为功能组件Tags
,但是在尝试删除this.
时似乎无法正确转换。
EditableTabGroup运行正常,但是当我在Tags
中渲染Taskform
时,它不起作用。
此外,如何清除状态标签,以便onCreate(submit)标签为空数组?
class EditableTagGroup extends React.Component {
state = {
tags: [],
inputVisible: false,
inputValue: ""
};
handleClose = removedTag => {
const tags = this.state.tags.filter(tag => tag !== removedTag);
console.log(tags);
this.setState({ tags });
};
showInput = () => {
this.setState({ inputVisible: true }, () => this.input.focus());
};
handleInputChange = e => {
this.setState({ inputValue: e.target.value });
};
handleInputConfirm = () => {
const { inputValue } = this.state;
let { tags } = this.state;
if (inputValue && tags.indexOf(inputValue) === -1) {
tags = [...tags, inputValue];
}
console.log(tags);
this.setState({
tags,
inputVisible: false,
inputValue: ""
});
};
saveInputRef = input => (this.input = input);
forMap = tag => {
const tagElem = (
<Tag
closable
onClose={e => {
e.preventDefault();
this.handleClose(tag);
}}
>
{tag}
</Tag>
);
return (
<span key={tag} style={{ display: "inline-block" }}>
{tagElem}
</span>
);
};
render() {
const { tags, inputVisible, inputValue } = this.state;
const tagChild = tags.map(this.forMap);
const { getFieldDecorator } = this.props;
return (
<div>
<div style={{ marginBottom: 16 }}>
<TweenOneGroup
enter={{
scale: 0.8,
opacity: 0,
type: "from",
duration: 100,
onComplete: e => {
e.target.style = "";
}
}}
leave={{ opacity: 0, width: 0, scale: 0, duration: 200 }}
appear={false}
>
{tagChild}
</TweenOneGroup>
</div>
{inputVisible && (
<Input
ref={this.saveInputRef}
onChange={this.handleInputChange}
onPressEnter={this.handleInputConfirm}
value={inputValue}
onBlur={this.handleInputConfirm}
type="text"
size="small"
style={{ width: 78 }}
/>
)}
{getFieldDecorator("tags", {
initialValue: this.state.tags
})(
<Input
ref={this.saveInputRef}
type="text"
size="small"
style={{ display: "none" }}
/>
)}
{!inputVisible && (
<Tag
onClick={this.showInput}
style={{ background: "#fff", borderStyle: "dashed" }}
>
<Icon type="plus" /> New Tag
</Tag>
)}
</div>
);
}
}
export default EditableTagGroup;
所以,为了使它起作用,我进行了2处更改:
1)您没有从文件中导出标签。在此示例中,我将其导出为命名导出,但是您可能应该将其导出为默认导出(export default Tags
)。
2)第二个问题是代码的这一部分:
const handleInputConfirm = () => {
if (inputValue && state.indexOf(inputValue) === -1) {
let state = [...state, inputValue];
}
setState(state);
setInputVisible(false);
setInputValue("");
};
在if条件中,在其中检查当前标签和用户要添加的标签,您定义了let
“状态”。这里有两个问题。第一个是在if块内分配一个let
,这意味着它不能从该块外部访问,因此,行setState(state)
只是将状态设置为相同状态(状态指的是状态变量state
,而不是您在if块中定义的新state
)。
第二个问题并不是真正的问题,您只应分配名称与上限范围内的变量相同的新变量。您可能现在已经知道这是一个坏习惯。
阅读有关let
及其范围规则here的更多信息。
这里是Tags
的完整工作代码:
import React, { useState } from "react";
import { Tag, Input, Icon } from "antd";
import { TweenOneGroup } from "rc-tween-one";
export const Tags = props => {
const [state, setState] = useState([]);
const [inputVisible, setInputVisible] = useState(false);
const [inputValue, setInputValue] = useState("");
const handleClose = removedTag => {
const tags = state.filter(tag => tag !== removedTag);
setState(tags);
};
const showInput = () => {
setInputVisible(true);
};
const handleInputChange = e => {
setInputValue(e.target.value);
};
const handleInputConfirm = () => {
if (inputValue && state.indexOf(inputValue) === -1) {
var newState = [...state, inputValue];
setState(newState);
}
setInputVisible(false);
setInputValue("");
};
const saveInputRef = input => (input = input);
const forMap = tag => {
const tagElem = (
<Tag
closable
onClose={e => {
e.preventDefault();
handleClose(tag);
}}
>
{tag}
</Tag>
);
return (
<span key={tag} style={{ display: "inline-block" }}>
{tagElem}
</span>
);
};
const tagChild = state.map(forMap);
const { getFieldDecorator } = props;
return (
<div>
<div style={{ marginBottom: 16 }}>
<TweenOneGroup
enter={{
scale: 0.8,
opacity: 0,
type: "from",
duration: 100,
onComplete: e => {
e.target.style = "";
}
}}
leave={{ opacity: 0, width: 0, scale: 0, duration: 200 }}
appear={false}
>
{tagChild}
</TweenOneGroup>
</div>
{inputVisible && (
<Input
ref={saveInputRef}
onChange={handleInputChange}
onPressEnter={handleInputConfirm}
value={inputValue}
onBlur={handleInputConfirm}
type="text"
size="small"
style={{ width: 78 }}
/>
)}
{getFieldDecorator("tags", {
initialValue: state.tags
})(
<Input
ref={saveInputRef}
type="text"
size="small"
style={{ display: "none" }}
/>
)}
{!inputVisible && (
<Tag
onClick={showInput}
style={{ background: "#fff", borderStyle: "dashed" }}
>
<Icon type="plus" /> New Tag
</Tag>
)}
</div>
);
};
关于重置标签,您可以在state
中定义Taskform.js
状态并将其作为道具传递给Tags
。这样,您可以在state
上重置setState([])
(Taskform.js
)。
Taskform.js:
const [tags, setTags] = useState([]);
const handleCreate = () => {
form.validateFields((err, values) => {
if (err) {
return;
}
form.resetFields();
onCreate(values);
setTags([]);
});
};
...
<Tags
getFieldDecorator={getFieldDecorator}
state={tags}
setState={setTags}
/>
Tags.js:
...
const { state, setState } = props;
当然您也应该从[state, setState] = useState([])
中删除Tags.js
。
希望有帮助!