1

I retrieved array data with checkbox using React. But if I checked one checkbox, it checks all. I want to show one text box if I checked one checkbox. How can I solve it?

class ColumnName extends Component {
  constructor(props) {
    super(props);
    this.state = { checked: false };
  }
  render() {
    if (!this.props.posts) {
      return <div />;
    }
    const content = this.state.checked ? <div> Content </div> : null;
    return (
      <ul>
        {this.props.posts.map(post => (
          <div>
            <Checkbox
              checked={this.state.checked}
              onChange={() => {
                this.setState({
                  checked: !this.state.checked
                });
              }}
            >
              {post.title}
            </Checkbox>
            {content}
          </div>
        ))}
      </ul>
    );
  }
}

export default Search;
1
  • You need to either hold the state checked state in each <Checkbox/>, or hold the states of all checkboxes in ColumName. Right now your checkboxes all map to the same value. Commented Jul 5, 2018 at 10:22

5 Answers 5

2

I solved that problem. Here is my code, I will try to explain it. First, I created an Array of objects.

const dogsData = [
{
    name: 'Jackey',
    src: require('./Images/dog-1.jpg'),
    id: 1,
    completed: false
}, {
    name: 'Molly',
    src: require('./Images/dog-2.jpg'),
    id: 2
    completed: false
}, {
    name: 'Spyke',
    src: require('./Images/dog-3.jpg'),
    id: 3,
    completed: false
},


]
export default dogsData;'

then I added that array into my state and I created a component for every object in this.state.dogs and add it props----

import dogsData from './components/dogsData'

constructor() {
super();
this.state = {
  dogs: dogsData,  //dogsData in state
}

const dogs = this.state.dogs.map(dog => {
  return (
    <Dogs dog={dog} key={dog.id} handleChange={this.handleChange} />
  )'

the handleChange method, add it to checkbox onChange event

handleChange(id) {
this.setState(prevState => {
  const updatedDogs = prevState.dogs.map(dog => {
    if (dog.id === id) {                
      dog.completed = !dog.completed    
    }
    else {                                      
      dog.completed = false
    }
    return dog
  })
  return {
    dogs: updatedDogs,
  }

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

1 Comment

Thanks friend, I used your logic and was able to fix the same problem.
1

You have an array of posts, and you want to render a Checkbox for each (it appears). You have one state value for the checked value of all the Checkboxes, on change you update this checked for every checkbox.

So that's your problem. Use a different checked state for every checkbox, but another option might be something akin to:

class ColumnName extends Component {
  constructor(props) {
    super(props);
    this.state = { selected: null };
  }

  render() {
    if (!this.props.posts) {
      return <div />;
    }

    // I assume content is something depending on which post is selected?!
    const content = this.state.selected ? <div> Content </div> : null;

    return (
      <ul>
        {this.props.posts.map(post => (
          <div>
            <Checkbox
              checked={this.state.selected === post.id}
              onChange={() => {
                this.setState({
                  selected: post.id,
                });
              }}
            >
              {post.title}
            </Checkbox>
            {content}
          </div>
        ))}
      </ul>
    );
  }
}

Comments

0

You currently only have one value checked that you use for every CheckBox. You could instead keep an object keeping track of if a particular post is checked on not.

Example

class ColumnName extends Component {
  state = { checked: {} };

  toggleChecked = title => {
    this.setState(previousState => {
      const checked = { ...previousState.checked };
      checked[title] = !checked[title];
      return { checked };
    });
  };

  render() {
    if (!this.props.posts) {
      return <div />;
    }

    return (
      <ul>
        {this.props.posts.map(post => (
          <div>
            <Checkbox
              checked={this.state.checked[post.title]}
              onChange={() => this.toggleChecked(post.title)}
            >
              {post.title}
            </Checkbox>
            {this.state.checked[post.title] ? <div> Content </div> : null}
          </div>
        ))}
      </ul>
    );
  }
}

Comments

0

You're reacting on state.checked to make your checkboxes checked or not: If one is checked, they're all going to be because they'll react on the same state field.

To overcome this issue try this :

  • Give all of your checkboxes an id and a key (you should get a warning if you do not do this anyway). You can just use the array id for this, it will work.
  • Make the state an object of { checkboxKey: checked } values

Example

class ColumnName extends Component {
  constructor(props) {
    super(props);
    this.state = { checked: {
      // Initial state ex. 0: true
    } };
  }
  render() {
    if (!this.props.posts) {
      return <div />;
    }

    return (
      <ul>
        {this.props.posts.map((post, id) => (
          <div key={id}>
            <Checkbox
              checked={this.state.checkboxes[i].checked}
              onChange={() => {
                this.setState({
                  checked: !this.checkboxes[i].checked
                });
              }}
            >
              {post.title}
            </Checkbox>
            {content}
          </div>
        ))}
      </ul>
    );
  }
}

export default Search;

Comments

0

Obviously all the posts are checked. It's because all the Checkbox use the same checked value (this.state.checked).

You can edit your example in different ways... For example you can save in your state what post has been checked and in the checked prop set true when you find in this.state.checkedPosts the post.

class Test extends React.Component {
  constructor(props) {
    super(props);
    this.state = { 
        checkedPosts: [] 
    };

  }

  handleChange(post){
    let index = -1;
    let checkedPosts = this.state.checkedPosts;

    checkedPosts.forEach((elem, idx) => {
        if(elem.title === post.title){
        index = idx;
      }
    })

    if(index === -1){
        checkedPosts.push(post.title);
    }else{
        checkedPosts.splice(index, 1);
    }

    this.setState({checkedPosts:checkedPosts})
  }

  findPostInChecked(post){
    let found = false;

    this.state.checkedPosts.forEach((elem) => {
        if(elem.title === post.title){
        found = true;
      }
   })

    return found;
  }    

  render() {
    const content = this.state.checked ? <div> Content </div> : null;
    return (
      <ul>
        {this.props.posts.map(post => (
          <div key={post.title}>
            <input type="checkbox"
              checked={this.findPostInChecked.bind(post) === true}
              key = {post.title}
              onChange={this.handleChange.bind(this, post)}
            />
            {post.title}
           {content}
          </div>
        ))}
      </ul>
    );
  }
}

ReactDOM.render(
  <Test posts = {[{title:"Hello"}, {title:"Bye"}]}/>,
  document.getElementById('container')
);

Comments

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.