【问题标题】:Render input fields dynamically inside a list在列表中动态呈现输入字段
【发布时间】:2019-07-23 12:25:58
【问题描述】:

我有一组组件,其中包含输入字段和文本行。 如图所示,用户应该能够添加类别和描述。添加它们后,它们将呈现为组件列表。像这样 在一个类别中,将有上图中给出的标签,要添加它们,我必须添加一个输入组件。仅当用户单击每个类别行下方的添加标签按钮时,此输入组件才可用。当用户点击它时,它应该启用输入(应该在所选类别行内呈现一个输入组件)并且应该能够在其上键入标签名称并保存它。只有当我单击添加标签按钮时,我才需要启用此输入字段。它应该只在选定的类别行中启用。这是我尝试过的代码。

import React, { Component, Fragment } from "react";
import { Button, Header, Input } from "semantic-ui-react";
import "semantic-ui-css/semantic.min.css";
import ReactDOM from "react-dom";

class App extends Component {
  state = {
    category: "",
    description: "",
    categories: []
  };

  onChange = (e, { name, value }) => {
    this.setState({ [name]: value });
  };

  addCategory = () => {
    let { category, description } = this.state;
    this.setState(prevState => ({
      categories: [
        ...prevState.categories,
        {
          id: Math.random(),
          title: category,
          description: description,
          tags: []
        }
      ]
    }));
  };

  addTag = id => {
    let { tag, categories } = this.state;
    let category = categories.find(cat => cat.id === id);
    let index = categories.findIndex(cat => cat.id === id);
    category.tags = [...category.tags, { name: tag }];
    this.setState({
      categories: [
        ...categories.slice(0, index),
        category,
        ...categories.slice(++index)
      ]
    });
  };

  onKeyDown = e => {
    if (e.key === "Enter" && !e.shiftKey) {
      console.log(e.target.value);
    }
  };

  tags = tags => {
    if (tags && tags.length > 0) {
      return tags.map((tag, i) => {
        return <Header key={i}>{tag.name}</Header>;
      });
    }
  };

  enableTagIn = id => {};

  categories = () => {
    let { categories } = this.state;
    return categories.map(cat => {
      return (
        <Fragment key={cat.id}>
          <Header>
            <p>
              {cat.title}
              <br />
              {cat.description}
            </p>
          </Header>
          <Input
            name="tag"
            onKeyDown={e => {
              this.onKeyDown(e);
            }}
            onChange={this.onChange}
          />
          <Button
            onClick={e => {
              this.addTag(cat.id);
            }}
          >
            Add
          </Button>
          {this.tags(cat.tags)}
        </Fragment>
      );
    });
  };

  render() {
    return (
      <Fragment>
        {this.categories()}
        <div>
          <Input name="category" onChange={this.onChange} />
          <Input name="description" onChange={this.onChange} />
          <Button onClick={this.addCategory}>Save</Button>
        </div>
      </Fragment>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

这是codesandbox 网址。 关于如何实现这一点的任何想法?

【问题讨论】:

    标签: html reactjs


    【解决方案1】:

    我通过使用函数组件和反应钩子更改了您的代码,并创建了具有自己状态的类别组件,如下所示:

       import React, { Fragment } from "react";
    import { Button, Header, Input } from "semantic-ui-react";
    import "semantic-ui-css/semantic.min.css";
    import ReactDOM from "react-dom";
    
    const App = () => {
      const [Category, setCategory] = React.useState({
        title: "",
        description: ""
      });
      const [Categories, setCategories] = React.useState([]);
      return (
        <div>
          {console.log(Categories)}
          <Input
            value={Category.title}
            onChange={e => setCategory({ ...Category, title: e.target.value })}
          />
          <Input
            value={Category.description}
            onChange={e =>
              setCategory({ ...Category, description: e.target.value })
            }
          />
          <Button onClick={() => setCategories([...Categories, Category])}>
            Save
          </Button>
          <div>
            {Categories.length > 0
              ? Categories.map(cat => <CategoryItem cat={cat} />)
              : null}
          </div>
        </div>
      );
    };
    
    const CategoryItem = ({ cat }) => {
      const [value, setvalue] = React.useState("");
      const [tag, addtag] = React.useState([]);
      const [clicked, setclicked] = React.useState(false);
      const add = () => {
        setclicked(false);
        addtag([...tag, value]);
      };
      return (
        <Fragment>
          <Header>
            <p>
              {cat.title}
              <br />
              {cat.description}
            </p>
          </Header>
          <Input
            name="tag"
            value={value}
            style={{ display: clicked ? "initial" : "none" }}
            onChange={e => setvalue(e.target.value)}
          />
          <Button onClick={() => (clicked ? add() : setclicked(true))}>Add</Button>
          <div>{tag.length > 0 ? tag.map(tagname => <p>{tagname}</p>) : null}</div>
        </Fragment>
      );
    };
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);
    

    这里是sandbox

    【讨论】:

    • 不错,但我正在寻找 React 类的实现。当你添加标签时,这个输入字段也应该被隐藏
    • @Tromesh 完成沙箱检查!而且func和class组件没有太大区别!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-07
    • 2019-02-23
    • 1970-01-01
    • 2014-02-05
    • 1970-01-01
    • 1970-01-01
    • 2020-09-19
    相关资源
    最近更新 更多