vendredi 22 janvier 2016

React setState not setting state in checkbox onChange handler on clicking first time

I have a global checkbox to de/select its child checkboxes, and it works almost as I expected. but, this.setState() not working when I click the global checkbox first time.

However, this.setState() started to work if I click on the next time!

I could not figure out what causes this with DevTools, and React Chrome tool.
Any help would be appreciated.

MainFileTable.jsx

import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from '../../actions/fileActions';
import { Grid, Col, Row, Table, Input } from 'react-bootstrap';
import MainFileTableToolbar from './MainFileTableToolbar';
import MainFileTableTbodyItem from'./MainFileTableTbodyItem';

export default class MainFileTable extends Component {
  constructor(props) {
    super(props);
    this.state = {
      item: null,
      globalCheckbox: false
    };
    this.handleGlobalCheckbox = this.handleGlobalCheckbox.bind(this);
  }

  componentDidMount() {
    let file = this.props.state.file;
    if (file) {
      this.createItem(file);
    }
  }

  componentWillReceiveProps(nextProps) {
    let uesr = this.props.state.user;
    let cookie = uesr.userInfo.SID;
    let filepath = uesr.storage_list[0].filepath;
    let file = nextProps.state.file;

    if (!file) {
      this.props.fileList(filepath, cookie);
    }

    if (!this.state.item && file) {
      this.createItem(file);
    }
  }

  createItem(file) {
    console.log(`this.state.globalCheckbox: ${this.state.globalCheckbox}`);
    let item = file.filelist.map((file, index) => {
      if (file.type === "FILE") {
        return (<MainFileTableTbodyItem
          {...file}
          img="images/ic-type-html5.svg"
          key={index}
          globalCheckboxState={this.state.globalCheckbox}
        />);
      } else {
        return (<MainFileTableTbodyItem
          {...file}
          img="images/ic-type-folder.svg"
          key={index}
          globalCheckboxState={this.state.globalCheckbox}
        />);
      }
    });

    this.setState({item: item});
  }

  handleGlobalCheckbox(e) {
    let checked = e.target.checked;
    console.log(`---checked: ${checked}`);
    this.setState({globalCheckbox: checked});
    console.log(`---globalCheckbox: ${this.state.globalCheckbox}`);
    let file = this.props.state.file;
    if (file) {
      this.createItem(file);
    }
 }

  render() {
    return (
      <Row className="main-filetable">
        <MainFileTableToolbar />
        <Col xs={12} className="main-filetable-contents padding-left padding-right">
          <Table hover>
            <thead>
              <tr>
                <th className="th-checkbox">
                  <Input
                    type="checkbox"
                    label=""
                    onChange={this.handleGlobalCheckbox}
                    checked={this.state.globalCheckbox}
                    defaultChecked={false}
                  />
                </th>
                <th>Name</th>
                <th>Size</th>
                <th>Date</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {this.state.item}
            </tbody>
          </Table>
        </Col>
      </Row>
    );
  }
}


let mapStateToProps = (state) => ({
  state: state
});

let mapDispatchToProps = (dispatch) => ({
  fileList: (filepath, cookie) => {
    dispatch(actions.fileList(filepath, cookie));
  },
});

export default connect(mapStateToProps, mapDispatchToProps)(MainFileTable);

MainFileTableTbodyItem.jsx

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Input } from 'react-bootstrap';
import filesize from 'filesize';
import ModalDoc from './../modal/ModalDoc';

class MainFileTableTbodyItem extends Component {
  constructor(props) {
    super(props);
    this.state = {
      showModal: false,
      singleCheckbox: false,
    };

    this.handleSingleCheckbox = this.handleSingleCheckbox.bind(this);
  }

  componentWillReceiveProps(nextProps) {
    console.log(nextProps.globalCheckboxState);
    this.setState({singleCheckbox: !nextProps.globalCheckboxState});
  }

  handleNameClick() {
    this.setState({
      showModal: true
    });
  }

  handleHide() {
    this.setState({
      showModal: false
    });
  }

  handleSingleCheckbox(e) {
    this.setState({singleCheckbox: e.target.checked});
  }

  renderType() {
    if (this.props.type === 'FOLDER') {
      return (
        <th className="th-name">
          <img src="images/ic-type-folder.svg" alt="" />
          <span>
            {this.props.name}
          </span>
        </th>
      );
    } else if (this.props.type === 'FILE') {
      return (
        <th className="th-name" onClick={this.handleNameClick.bind(this)}>
          <img src={this.props.img} alt="" />
          <span>
            {this.props.name}
          </span>

          <ModalDoc
            show={this.state.showModal}
            onHide={this.handleHide.bind(this)}
          />

        </th>
      );
    }
  }

  render() {
    return (
      <tr>
        <th className="th-checkbox">
          <Input
            type="checkbox"
            label=""
            onChange={this.handleSingleCheckbox}
            checked={this.state.singleCheckbox}
          />
        </th>
        {this.renderType()}
        <th>
          {
            this.props.type === 'FOLDER'
            ? '-'
            : filesize(this.props.size, {bits: true})
          }
        </th>
        <th>
          {this.props.modified}
        </th>
        <th>
        </th>
      </tr>
    );
  }
}




let mapStateToProps = (state) => ({
  state: state
});

export default connect(mapStateToProps)(MainFileTableTbodyItem);




Aucun commentaire:

Enregistrer un commentaire