React js - 材质 ui - 传输列表 - 使用旧状态
Posted
技术标签:
【中文标题】React js - 材质 ui - 传输列表 - 使用旧状态【英文标题】:React js - material ui - transfer list -- using old states 【发布时间】: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"
>
>
</Button>
<Button
variant="outlined"
size="small"
//className=classes.button
onClick=this.handleCheckedLeft
disabled=rightChecked.length === 0
aria-label="move selected left"
>
<
</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
【问题讨论】:
【参考方案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 语句之前)。不过,我当然不是这方面的专家。以上是关于React js - 材质 ui - 传输列表 - 使用旧状态的主要内容,如果未能解决你的问题,请参考以下文章
使用 @testing-library/react 测试材质 ui 滑块
如何使用 react-dnd 从材质 UI 中拖放 TableHeaderColumn?