1

I am working on this project where my requirement is to create dynamic checkboxes on the fly on runtime. I get values in array from API in componentWillMount and the array looks like this:

["Diesel", "SomeTeam", "demo", "lazyTeam", "demoTeam", "X & G", "Kteam"]

I have been breaking my head over this to solve this and so far I've been creating dynamic states in componentWillMount to mark all checkboxes initially False and the component I am rendering the checkboxes by parsing the array with map function.

componentWillMount looks like this:

axios.get(`/teams/tlist`).then(response => {
    let tempTeamArr = []
    Object.keys(response.data.teams).map((key, index) => {
      tempTeamArr.push(response.data.teams[key].name)
      console.log(tempTeamArr)
      if(index == Object.keys(response.data.teams).length-1) {
        this.setState({
          allTeams: tempTeamArr,
          [`${response.data.teams[key].name}CheckedStat`]: false
        }, () => {
          console.log(`dynamic state: this.state[${response.data.teams[key].name}CheckedStat]`, this.state[`${response.data.teams[key].name}CheckedStat`])
        })
      }
    })
  })

and my checkbox component looks like this:

{allTeams.map((data, index) => {
return (
    <Checkbox
        label={data}
        id={data}
        checked={this.state[`${data}CheckedStat`]}
        onChecked={bool => {this.setState({[`${data}CheckedStat`]: !this.state[`${data}CheckedStat`]})}}
        />
)})

Checkbox component code is:

const Checkbox = ({ label, id, onChecked, checked }) => (
<StyledCheckbox>
    <input
      className="checkbox"
      type="checkbox"
      id={id}
      value={id}
      onChange={e => onChecked(e.target.checked)}
      checked={checked}
    />
    <label htmlFor={id}>{label}</label>
  </StyledCheckbox>
)

export { Checkbox }

Problem I am facing is, this renders checkboxes but the check uncheck is very erratic and out of control. I need your help real bad and would be really greatful if you could help me solve this. This will help more people like me who are stuck on such trivial UI rendering issue yet complex problem.

Thank you.

8
  • 1
    first, just remark, is it okay to update state property allTeams: tempTeamArr every iteration? Commented Oct 12, 2017 at 6:51
  • What do you mean by erratic? Can you provide working example? Commented Oct 12, 2017 at 7:02
  • @DanilGholtsman Thanks for pointing it out, I've corrected the above code Commented Oct 12, 2017 at 7:30
  • Hi @AndrzejSmyk , erratic as in if I click 2nd checkbox then the first checkbox gets checked and vice-versa. Commented Oct 12, 2017 at 7:32
  • 1
    Think I know what might be problem here. Please add response from API. You mentioned you should get array but your code shows it is rather object? Commented Oct 12, 2017 at 8:20

2 Answers 2

2

Just from the top of my head, I came up with this soultion. Ugly, but suppose to work.

Ofc you can make it simplier by using checkbox component etc. Hope you get the idea.

For simplyfying thing, just filled up array like that

componentWillMount() {
    var me = this,
      teams = ["Diesel", "SomeTeam", "demo", "lazyTeam", "demoTeam", "X & G", "Kteam"],
      setupCheckboxes = (function () {
        return teams.map((el) => {
          return  {
            teamName: el,
            isChecked: false
          }
        });
      })();

    this.setState({
      allTeamsCbData: setupCheckboxes
    });
  }

On render

 render() {
    let teamsCbData = this.state.allTeamsCbData,
      me = this;
    return (
      <div>
        {teamsCbData.map((el, index) => {
          return (
            <div key={el.teamName}>
              <input type="checkbox" name={el.teamName} checked={el.isChecked} onChange={
                  function () {
                    let curData = me.state.allTeamsCbData,
                        id = curData.findIndex(function(elem){ return elem.teamName == el.teamName});

                        curData[id].isChecked = !curData[id].isChecked;

                    me.setState({allTeamsCbData:curData})
                  }
                } />
              <label >{el.teamName}</label>
            </div>
          );
        })}
      </div>
    );
  };

Btw what do you meant by that?

check uncheck is very erratic

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

3 Comments

Hi @Danil , I solved it, it was an issue related to other state setting first before checkbox' state which made the checkbox check/uncheck very random (erratic and uncontrolled). Before checkbox state could set, the app would render.
Oh, that's good to know! You can close question then i suppose
Yep, closing the question @Danil, thank you for your efforts man :)
2

Okay, I've solved it.

The problem was like:

<DropDownBox style={{ marginRight: '30px' }} className="DropDownBoxA" onClick={e=>this.toggleDropDownView}>
  <DropdownView style={DropdownViewVisibleA ? { opacity: '1', zIndex: '1' } : { opacity: '0', zIndex: '-1' }} className="DropdownViewA"> 
                ... rest UL LI list code

  </DropdownView>
</DropDownBox>

the problem was in this.toggleDropDownView, when the dropdown view is visible and I try to check the checkboxes in the dropdown view, first setState within toggleDropDown function fires which forces the view to re-render and the state of clicked checkbox fails to render immediately. When I check a checkbox, close the dropdow and opens it again, i see the checkbox checked.

I corrected the state conflict issue by rewriting the above code with a slight change like this:

<DropDownBox style={{ marginRight: '30px' }} className="DropDownBoxA" onClick={e=>this.setState({ DropdownViewVisibleA: !this.state.DropdownViewVisibleA, DropdownViewVisibleB: false })}>
  <DropdownView style={DropdownViewVisibleA ? { opacity: '1', zIndex: '1' } : { opacity: '0', zIndex: '-1' }} className="DropdownViewA"> 
                ... rest UL LI list code

  </DropdownView>
</DropDownBox>

Hope this helps others and thank you tons everyone for your efforts to help me solve this.

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.