【问题标题】:React js - material ui - transfer list -- using old statesReact js - 材质 ui - 传输列表 - 使用旧状态
【发布时间】:2021-02-04 04:01:00
【问题描述】:

我正在制作一个反应应用程序并尝试在材料 ui 上重新创建此传输列表演示 - 使用旧的状态方法。但是我掉进了一些陷阱。

当前沙箱 https://codesandbox.io/s/morning-voice-qrym9?file=/src/TransferList.js

https://material-ui.com/components/transfer-list/ - 基于简单列表 - 我正在尝试将其重新创建为组件 - 遵循其余组件的构建方式 - 但函数和状态声明中的内容是造成错误的连锁反应

我当前的代码。

import React, { Component } from 'react'
import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';


import Grid from '@material-ui/core/Grid';
import List from '@material-ui/core/List';
import Card from '@material-ui/core/Card';
import CardHeader from '@material-ui/core/CardHeader';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import Checkbox from '@material-ui/core/Checkbox';
import Button from '@material-ui/core/Button';
import Divider from '@material-ui/core/Divider';


import './TransferList.scss';

class TransferList extends Component {
  
  constructor(props, context) {
    super(props, context);
    this.state = {
      checked: [],
      left: [0, 1, 2, 3],
      right: [4, 5, 6, 7]
    };
  }


  not(a, b) {
    //return a.filter((value) => b.indexOf(value) === -1);
  }

  intersection(a, b) {
    //return a.filter((value) => b.indexOf(value) !== -1);
  }

  union(a, b) {
    //return [...a, ...this.not(b, a)];
  }



  numberOfChecked(items) {
    //return this.intersection(this.state.checked, items).length;
  }

  handleToggleAll(items) {
    if (this.numberOfChecked(items) === items.length) {

      this.state = {
        checked: this.not(this.state.checked, items),
      };
    } else {

      this.state = {
        checked: this.union(this.state.checked, items),
      };
    }
  };
  
  handleCheckedRight() {
   const leftChecked = this.intersection(this.state.checked, this.state.left);
    this.state = {
      right: this.state.right.concat(leftChecked),
      left: this.not(this.state.left, leftChecked),
      checked: this.not(this.state.checked, leftChecked),
    };
  };

  handleCheckedLeft() {
   const rightChecked = this.intersection(this.state.checked, this.state.right);

    this.state = {
      right: this.not(this.state.right, rightChecked),
      left: this.state.left.concat(rightChecked),
      checked: this.not(this.state.checked, rightChecked),
    };
  };

 customList(title, items) {
  return (
      <Card>
        <CardHeader
          //className={classes.cardHeader}
          avatar={
            <Checkbox
              onClick={this.handleToggleAll(items)}
              checked={this.numberOfChecked(items) === items.length && items.length !== 0}
              indeterminate={this.numberOfChecked(items) !== items.length && this.numberOfChecked(items) !== 0}
              disabled={items.length === 0}
              inputProps={{ 'aria-label': 'all items selected' }}
            />
          }
          title={title}
          subheader={`${this.numberOfChecked(items)}/${items.length} selected`}
        />
        <Divider />
        <List 
          //className={classes.list} 
          dense 
          component="div" 
          role="list"
        >
          
          <ListItem />
        </List>
      </Card>
    );
 }



  render() {



    const leftChecked = this.intersection(this.state.checked, this.state.left);
    const rightChecked = this.intersection(this.state.checked, this.state.right);
/*
    const handleToggle = (value) => () => {
      const currentIndex = checked.indexOf(value);
      const newChecked = [...checked];

      if (currentIndex === -1) {
        newChecked.push(value);
      } else {
        newChecked.splice(currentIndex, 1);
      }

      setChecked(newChecked);
    };

    const numberOfChecked = (items) => this.intersection(checked, items).length;

    const handleToggleAll = (items) => () => {
      if (numberOfChecked(items) === items.length) {
        setChecked(not(checked, items));
      } else {
        setChecked(union(checked, items));
      }
    };

    const handleCheckedRight = () => {
      setRight(right.concat(leftChecked));
      setLeft(not(left, leftChecked));
      setChecked(not(checked, leftChecked));
    };

    const handleCheckedLeft = () => {
      setLeft(left.concat(rightChecked));
      setRight(not(right, rightChecked));
      setChecked(not(checked, rightChecked));
    };

    const customList = (title, items) => (
      <Card>
        <CardHeader
          className={classes.cardHeader}
          avatar={
            <Checkbox
              onClick={handleToggleAll(items)}
              checked={numberOfChecked(items) === items.length && items.length !== 0}
              indeterminate={numberOfChecked(items) !== items.length && numberOfChecked(items) !== 0}
              disabled={items.length === 0}
              inputProps={{ 'aria-label': 'all items selected' }}
            />
          }
          title={title}
          subheader={`${numberOfChecked(items)}/${items.length} selected`}
        />
        <Divider />
        <List className={classes.list} dense component="div" role="list">
          {items.map((value) => {
            const labelId = `transfer-list-all-item-${value}-label`;

            return (
              <ListItem key={value} role="listitem" button onClick={handleToggle(value)}>
                <ListItemIcon>
                  <Checkbox
                    checked={checked.indexOf(value) !== -1}
                    tabIndex={-1}
                    disableRipple
                    inputProps={{ 'aria-labelledby': labelId }}
                  />
                </ListItemIcon>
                <ListItemText id={labelId} primary={`List item ${value + 1}`} />
              </ListItem>
            );
          })}
          <ListItem />
        </List>
      </Card>
    );

*/


    return (
      <Grid container spacing={2} justify="center" alignItems="center">
        <Grid item>{this.customList('Choices', this.state.left)}</Grid>
        <Grid item>
          <Grid container direction="column" alignItems="center">
            <Button
              variant="outlined"
              size="small"
              //className={classes.button}
              onClick={this.handleCheckedRight}
              disabled={leftChecked.length === 0}
              aria-label="move selected right"
            >
              &gt;
            </Button>
            <Button
              variant="outlined"
              size="small"
              //className={classes.button}
              onClick={this.handleCheckedLeft}
              disabled={rightChecked.length === 0}
              aria-label="move selected left"
            >
              &lt;
            </Button>
          </Grid>
        </Grid>
        <Grid item>{this.customList('Chosen', this.state.right)}</Grid>
      </Grid>
    )
  }
}


function mapStateToProps(state) {
  return {
  };
}

function mapDispatchToProps(dispatch) {
 return bindActionCreators({  }, dispatch);
}

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(TransferList))



////////

/*

export default function TransferList() {
  const classes = useStyles();
  const [checked, setChecked] = React.useState([]);
  const [left, setLeft] = React.useState([0, 1, 2, 3]);
  const [right, setRight] = React.useState([4, 5, 6, 7]);

  const leftChecked = intersection(checked, left);
  const rightChecked = intersection(checked, right);

  const handleToggle = (value) => () => {
    const currentIndex = checked.indexOf(value);
    const newChecked = [...checked];

    if (currentIndex === -1) {
      newChecked.push(value);
    } else {
      newChecked.splice(currentIndex, 1);
    }

    setChecked(newChecked);
  };

  const numberOfChecked = (items) => intersection(checked, items).length;

  const handleToggleAll = (items) => () => {
    if (numberOfChecked(items) === items.length) {
      setChecked(not(checked, items));
    } else {
      setChecked(union(checked, items));
    }
  };

  const handleCheckedRight = () => {
    setRight(right.concat(leftChecked));
    setLeft(not(left, leftChecked));
    setChecked(not(checked, leftChecked));
  };

  const handleCheckedLeft = () => {
    setLeft(left.concat(rightChecked));
    setRight(not(right, rightChecked));
    setChecked(not(checked, rightChecked));
  };

  const customList = (title, items) => (
    <Card>
      <CardHeader
        className={classes.cardHeader}
        avatar={
          <Checkbox
            onClick={handleToggleAll(items)}
            checked={numberOfChecked(items) === items.length && items.length !== 0}
            indeterminate={numberOfChecked(items) !== items.length && numberOfChecked(items) !== 0}
            disabled={items.length === 0}
            inputProps={{ 'aria-label': 'all items selected' }}
          />
        }
        title={title}
        subheader={`${numberOfChecked(items)}/${items.length} selected`}
      />
      <Divider />
      <List className={classes.list} dense component="div" role="list">
        {items.map((value) => {
          const labelId = `transfer-list-all-item-${value}-label`;

          return (
            <ListItem key={value} role="listitem" button onClick={handleToggle(value)}>
              <ListItemIcon>
                <Checkbox
                  checked={checked.indexOf(value) !== -1}
                  tabIndex={-1}
                  disableRipple
                  inputProps={{ 'aria-labelledby': labelId }}
                />
              </ListItemIcon>
              <ListItemText id={labelId} primary={`List item ${value + 1}`} />
            </ListItem>
          );
        })}
        <ListItem />
      </List>
    </Card>
  );


*/

//////////

最新的沙盒工作 https://codesandbox.io/s/morning-voice-qrym9?file=/src/TransferList.js

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    可能不是完整的答案,而是在 customList() 中:

    onClick={this.handleToggleAll(items)}
    

    调用方法而不是将其设置为事件处理程序,您可能想要:

    onClick={() => this.handleToggleAll(items)}
    

    【讨论】:

    • codesandbox.io/s/morning-voice-qrym9?file=/src/TransferList.js -- 我设法显示了复选框 -- 但点击它们没有影响?
    • 你在哪里 this.state = { stuff here } 我希望你想要 this.setState({ stuff here }) (除了构造函数)。编辑:从您的代码和框链接的外观来看,它似乎在它认为这是一个问题的地方放置了一个黄色的波浪线。
    • 好地方 - 好的 好的 - 我们现在接近了 - 复选框检查 - 但我似乎无法在左/右传输按钮上进行任何操作 - codesandbox.io/s/morning-voice-qrym9?file=/src/TransferList.js
    • codesandbox.io/s/morning-voice-qrym9?file=/src/TransferList.js -- 搞定了 -- 谢谢大佬 -- 我们如何改进 -- 更紧凑
    • 我要做的很多事情可能是相当主观的,但我会提到几件事:我可能会将 not、intersection 和 union 函数删除到类定义之外的某个地方——它们感觉就像不是特定于类的通用实用程序功能;我可能会分解左右函数(例如handleCheckedLeft),因为它们只是在不同的列表上做同样的事情;在 customList 中,我可能会计算 this.numberOfChecked(items) 一次(在 return 语句之前)。不过,我当然不是这方面的专家。
    猜你喜欢
    • 2018-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-03
    • 1970-01-01
    • 1970-01-01
    • 2020-09-14
    • 2022-01-23
    相关资源
    最近更新 更多