动态添加/删除输入ReactJS

时间:2018-08-29 13:22:57

标签: reactjs

我是React的新手,这些状态值会杀死我!我想做的是在input上加上select options,并将每个select option连接到其input,当我删除它们时,我想一起删除它们没有发生。

当我删除任何一个时,只会删除最后一行,而select option不会保留相同的input

这是我的代码:

  import React, { Component } from 'react';
  class SocialMedia extends Component {
  constructor() {
    super();
    this.state = {
      name: '',
      SocialData: [],
      socialArray: [
        {
        "id": 1,
        "name": "Website",
        "regex": "(https|http):\\/\\/(www\\.)*"
        },
        {
        "id": 4,
        "name": "Last.fm",
        "regex": "(https|http):\\/\\/www\\.(lastfm\\.com|last\\.fm\\/|lastfm\\.ch).*"
        },
        {
        "id": 5,
        "name": "Facebook",
        "regex": "https:\\/\\/www\\.facebook\\.com\\/.*"
        },
        {
        "id": 6,
        "name": "Twitter",
        "regex": "(https|http):\\/\\/(twitter\\.com).*"
        },
        {
        "id": 8,
        "name": "Instagram",
        "regex": "https:\\/\\/(instagr\\.am\\/.*|instagram\\.com\\/.*)"
        },
        {
        "id": 9,
        "name": "YouTube Channel",
        "regex": "((http|https):\\/\\/|)(www\\.)?youtube\\.com\\/(channel\\/|user\\/)[a-zA-Z0-9]{1,}"
        },
        {
        "id": 11,
        "name": "YouTube Video",
        "regex": "^.*(youtu.be\\/|v\\/|e\\/|u\\/\\w+\\/|embed\\/|v=)([^#\\&\\?]*).*"
        },
        {
        "id": 12,
        "name": "Spotify",
        "regex": "spotify\\:+"
        }
        ]
    };
    this.handleAddSocial = this.handleAddSocial.bind(this);
    this.handleInputVlaueChange = this.handleInputVlaueChange.bind(this);
    this.handleRemoveSocial = this.handleRemoveSocial.bind(this);
    this.selectHandler = this.selectHandler.bind(this);
  }

  handleAddSocial () {
    let array = this.state.SocialData;
    array.push({ id: array.length+1 , socialname: '' })
    this.setState({ SocialData: array})
  }

  handleInputVlaueChange (e ) {
    console.log(e.target.value)
  }

  handleRemoveSocial (e) {
    let someArray = this.state.SocialData;
    someArray.splice( someArray.indexOf(e), 1);
    this.setState({ SocialData: someArray })
  }

  render() {
    return (
      <div >
        <button  
          className="newFlyerButton btn mb-4"
          type="button" 
          onClick={this.handleAddSocial}
        >
          <span>
            <img src={plus} alt="plus" className="newFlyerPlus"/>
            <span className="buttonText">ADD NEW</span>
          </span>
        </button>

        <table className="table mt-3 bordered table-hover  white-table addNewSocial">
          <tbody>
            {this.state.SocialData.map((Social, idx) => (
              <tr key={idx} className="row Social">
                <td className="col-6 socialInput">
                  <input
                    type="text"
                    placeholder={`Add New # ${idx+1}`}
                    value={Social.name}
                    onChange={this.handleInputVlaueChange}
                  />
                </td>
                <td className="col-4 socialSelector">
                  <select defaultValue="SelectOption">
                    <option value="SelectOption" disabled >Select your option</option>
                    { this.state.socialArray.map(socidata =>
                      <option 
                        value={socidata.name} 
                        data={socidata} 
                        key={socidata.id}
                      >
                        {socidata.name}
                      </option>
                    )}
                  </select>
                </td>
                <td className="col-2 closingLink">
                  <i className="fas fa-fw fa-times" onClick={ () => this.handleRemoveSocial(idx) }></i>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    )
  }
}

export default SocialMedia;

如何将每个社交媒体选择与相同的输入连接起来?

1 个答案:

答案 0 :(得分:3)

据我了解,您想基于发送到handleRemoveSocial的索引来删除正确的输入,并且还要跟踪每个输入的社交名称,对吗?

要解决您的问题,请进行以下更改:

  1. 由于handleRemoveSocial已经收到idx,因此您不需要使用indexOf,因此:someArray.splice( someArray.indexOf(e), 1);成为someArray.splice(e, 1);

  2. 您需要跟踪<select>的更改并相应地更改您的状态,为此,您应该使用类似handleSocialNameChange的方法来设置具有社交名称的新状态。

  3. p>
  4. 使用socialname的每个对象内的this.state.SocialData字段在<select>上呈现选定的选项。

经过修改的代码:

import React, { Component } from 'react';

class SocialMedia extends Component {
  constructor() {
    super();
    this.state = {
      name: '',
      SocialData: [],
      socialArray: [
        {
        "id": 1,
        "name": "Website",
        "regex": "(https|http):\\/\\/(www\\.)*"
        },
        {
        "id": 4,
        "name": "Last.fm",
        "regex": "(https|http):\\/\\/www\\.(lastfm\\.com|last\\.fm\\/|lastfm\\.ch).*"
        },
        {
        "id": 5,
        "name": "Facebook",
        "regex": "https:\\/\\/www\\.facebook\\.com\\/.*"
        },
        {
        "id": 6,
        "name": "Twitter",
        "regex": "(https|http):\\/\\/(twitter\\.com).*"
        },
        {
        "id": 8,
        "name": "Instagram",
        "regex": "https:\\/\\/(instagr\\.am\\/.*|instagram\\.com\\/.*)"
        },
        {
        "id": 9,
        "name": "YouTube Channel",
        "regex": "((http|https):\\/\\/|)(www\\.)?youtube\\.com\\/(channel\\/|user\\/)[a-zA-Z0-9]{1,}"
        },
        {
        "id": 11,
        "name": "YouTube Video",
        "regex": "^.*(youtu.be\\/|v\\/|e\\/|u\\/\\w+\\/|embed\\/|v=)([^#\\&\\?]*).*"
        },
        {
        "id": 12,
        "name": "Spotify",
        "regex": "spotify\\:+"
        }
        ]
    };
    this.handleAddSocial = this.handleAddSocial.bind(this);
    this.handleInputValueChange = this.handleInputValueChange.bind(this);
    this.handleRemoveSocial = this.handleRemoveSocial.bind(this);
    this.handleSocialNameChange = this.handleSocialNameChange.bind(this);
    this.selectHandler = this.selectHandler.bind(this);
  }

  handleAddSocial () {
    let array = this.state.SocialData;
    array.push({ id: array.length+1 , socialname: '' })
    this.setState({ SocialData: array})
  }

  handleInputValueChange(e, idx) {
    let nextSocialData = this.state.SocialData.slice();
    nextSocialData[idx].name = e.target.value;
    this.setState({ SocialData: nextSocialData });
  }

  handleSocialNameChange(socialName, idx) {
    let nextSocialData = this.state.SocialData.slice();
    nextSocialData[idx].socialname = socialName;
    this.setState({ SocialData: nextSocialData });
  }

  handleRemoveSocial(idx) {
    let someArray = this.state.SocialData;
    someArray.splice(idx, 1);
    this.setState({ SocialData: someArray });
  }

  render() {
    return (
      <div >
        <button  
          className="newFlyerButton btn mb-4"
          type="button" 
          onClick={this.handleAddSocial}
        >
          <span>
            <img src={plus} alt="plus" className="newFlyerPlus"/>
            <span className="buttonText">ADD NEW</span>
          </span>
        </button>

        <table className="table mt-3 bordered table-hover  white-table addNewSocial">
          <tbody>
            {this.state.SocialData.map((Social, idx) => (
              <tr key={idx} className="row Social">
                <td className="col-6 socialInput">
                  <input
                    type="text"
                    placeholder={`Add New # ${idx+1}`}
                    value={Social.name}
                    onChange={this.handleInputValueChange}
                  />
                </td>
                <td className="col-4 socialSelector">
                  <select
                    onChange={e => {
                      this.handleSocialNameChange(e.target.value, idx);
                    }}
                    value={Social.socialname || "SelectOption"}
                  >
                    <option value="SelectOption" disabled >Select your option</option>
                    { this.state.socialArray.map(socidata =>
                      <option 
                        value={socidata.name} 
                        data={socidata} 
                        key={socidata.id}
                      >
                        {socidata.name}
                      </option>
                    )}
                  </select>
                </td>
                <td className="col-2 closingLink">
                  <i className="fas fa-fw fa-times" onClick={ () => this.handleRemoveSocial(idx) }></i>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    )
  }
}

export default SocialMedia;

我还使用这些更改创建了CodeSandbox,还进行了一些修改,以便代码可以运行(例如删除未定义的selectHandler)。

我希望这会有所帮助。干杯!