ReactJs: set initial state using props while using dynamic Taglist

809 Views Asked by At

I am sending an array named tags as props and i want to assign it in initial states so that those array elements should be displayed. using this code they are displayed properly but i am unable to edit them. when i click cross it gets deleted but after sometime it displays again. Seems like setState in handelClose method is not working.

import React from 'react';
import ReactDOM from 'react-dom';
import { Tag, Input, Tooltip, Button } from 'antd';

class EditableTagGroup extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      tags: [],
      inputVisible: false,
      inputValue: '',
    };
  }

  handleClose = (removedTag) => {
    // debugger;
    const tags = this.state.tags.filter(tag => tag !== removedTag);
    console.log(tags);
    // debugger;
    this.setState({ tags: tags });
  }

  showInput = () => {
    this.setState({ inputVisible: true }, () => this.input.focus());
  }

  handleInputChange = (e) => {
    this.setState({ inputValue: e.target.value });
  }

  handleInputConfirm = () => {
    const state = this.state;
    const inputValue = state.inputValue;
    let tags = state.tags;
    if (inputValue && tags.indexOf(inputValue) === -1) {
      tags = [...tags, inputValue];
    }
    console.log(tags);
    this.setState({
      tags,
      inputVisible: false,
      inputValue: '',
    });
    this.props.onSelect(tags);
  }

  // componentDidUpdate(prevProps, prevState) {
  //   this.setState({tags: this.props.tags})
  // }

  componentDidUpdate(prevProps, prevState) {
    // debugger;
    if (this.state.tags  !== this.props.tags) {
      this.setState({tags: this.props.tags})
    }
  }

  saveInputRef = input => this.input = input

  render() {
    const {tags , inputVisible, inputValue } = this.state;
    return (
      <div>
        {tags.map((tag, index) => {
          const isLongTag = tag.length > 20;
          const tagElem = (
            <Tag key={tag} closable={index !== -1} afterClose={() => this.handleClose(tag)}>
              {isLongTag ? `${tag.slice(0, 20)}...` : tag}
            </Tag>
          );
          return isLongTag ? <Tooltip title={tag} key={tag}>{tagElem}</Tooltip> : tagElem;
        })}
        {inputVisible && (
          <Input
            ref={this.saveInputRef}
            type="text"
            size="small"
            style={{ width: 78 }}
            value={inputValue}
            onChange={this.handleInputChange}
            onBlur={this.handleInputConfirm}
            onPressEnter={this.handleInputConfirm}
          />
        )}
        {!inputVisible && <Button size="small" type="dashed" onClick={this.showInput}>+ New Tag</Button>}
      </div>
    );
  }
}

export default EditableTagGroup
1

There are 1 best solutions below

2
On

The problem is that, you are saving and using the props in the local state and then modifying those, however everytime the component updates, you are setting the state back to the props.

// this is where you are setting the state back to 
// props and hence your edit disappears
componentDidUpdate(prevProps, prevState) {
    // debugger;
    if (this.state.tags  !== this.props.tags) {
      this.setState({tags: this.props.tags})
    }
  }

What you need to do is to not maintain, the props in state but rather directly modifying it, by passing a handler from the parent to update the props.

See this answer on how to pass and update data in parent

How to pass data from child component to its parent in ReactJS?