0

I am new on React and these state values are going to kill me! What I am trying to do is add input with select optionsand each select optionis connected to its inputand when I delete on of them I want to delete them together but this is not happening.

When I delete any one, only the last line is deleted and the select option does not stick with the same input.

This is my code:

  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;

How can I connect each social media selection with the same input in line?

2
  • Where is declared selectHandler ? Commented Aug 29, 2018 at 13:40
  • Please add your current result and expected result so we understand better. Also, a sandbox example is also very useful for anyone to help you a bit faster ;) Commented Aug 29, 2018 at 14:14

1 Answer 1

5

From what I understood, you want to remove the correct input based on the index you send to handleRemoveSocial and also keep track of the social name of each input, right?

To solve your problem, these are some changes you should make:

  1. Since handleRemoveSocial already receives idx, you don't need to use indexOf, so: someArray.splice( someArray.indexOf(e), 1); becomes someArray.splice(e, 1);

  2. You need to keep track of <select> changes and change your state accordingly, for that, you should have a method like handleSocialNameChange that sets a new state with the social name.

  3. Use the socialname field inside each object of this.state.SocialData to render the selected option on <select>.

Code with the modifications:

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;

I've also created a CodeSandbox with these changes and also made some modifications so the code could run (like removing selectHandler which isn't defined).

I hope this helps. Cheers!

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you - Thiago it is working for the selection option but if you have 3 inputs and fill the input with anything , you will see that when you delete the second line the last value line will be deleted not the second one.
Edited the answer and the sandbox to implement handleInputValueChange. This makes the input controlled via Social.name
Working perfectly, Thank you so much Thiago you made my day God bless you
@Thiago Murakami Just 1 question. How can we clear the input field when we change the value from dropdown.
Please someone help me clearing the input fields when we change the value of dropdown

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.