将反应类组件转换为反应无状态组件

时间:2017-08-14 09:02:42

标签: javascript reactjs ecmascript-6 stateless

我尝试将反应类组件转换为无状态组件,我不是一个具有复杂无状态组件的goood。这样做的最佳做法是什么?现在我已经得到了组件,Table和EnchanceTable,我想将Table转换为无状态,所有的功能都在我内部且没有任何状态。我已经开始使用了这个,但不太确定它是否真的如此。

表组件(应该是无状态的)

class Table extends React.Component {

    static propTypes = {
        columns: PropTypes.arrayOf(columnsShape),
    }

    constructor(props) {
        super(props)
        this.state = {
            order: 'asc',
            orderBy: this.props.orderBy,
            selected: [],
            searchValue: '',
            data: this.props.data,
            filterData: this.props.data,
        }
    }

    defaultCellRenderer = ({item, dataKey}) =>
        item[dataKey]

    handleRequestSort = (event, property) => {
        const orderBy = property
        let order = 'desc'

        if (this.state.orderBy === property && this.state.order === 'desc') {
            order = 'asc'
        }

        const filterData = this.state.filterData.sort(
      (a, b) => order === 'desc' ? b[orderBy] > a[orderBy] : a[orderBy] > b[orderBy],
    )

        this.setState({ filterData, order, orderBy })
    }

    handleSelectAllClick = (event, checked) => {
        const {data,selected, onSelectAll} = this.props
        if (checked) {
            this.setState({ selected: this.state.data.map(item => item.id) })
        }
        else
        this.setState({ selected: [] })
    }

    unselectSelected = () => {
        this.setState({selected: []})
    }

    deleteSelected = () => {
        const {data, selected, onDelete} = this.props

        onDelete(selected)
    }

    handleKeyDown = (event, id) => {
        if (keycode(event) === 'space') {
            this.handleClick(event, id)
        }
    }

    handleClick = (event, id) => {
        const { selected } = this.state
        const selectedIndex = selected.indexOf(id)
        let newSelected = []

        if (selectedIndex === -1) {
            newSelected = newSelected.concat(selected, id)
        } else if (selectedIndex === 0) {
            newSelected = newSelected.concat(selected.slice(1))
        } else if (selectedIndex === selected.length - 1) {
            newSelected = newSelected.concat(selected.slice(0, -1))
        } else if (selectedIndex > 0) {
            newSelected = newSelected.concat(
        selected.slice(0, selectedIndex),
        selected.slice(selectedIndex + 1),
      )
        }

        this.setState({ selected: newSelected })
    }

    handleSearch = event => {
        const {data} = this.state
        let filteredDatas = []
        filteredDatas = data.filter(e => {
            let mathedItems = Object.values(e)
            let returnedItems
            mathedItems.forEach(e => {
                const regex = new RegExp(event.target.value, 'gi')
                if (typeof e == 'string')
                    returnedItems = e.match(regex)
            })
            return returnedItems
        })
        this.setState({filterData: filteredDatas, searchValue: event.target.value})
    }

    isSelected = id => this.state.selected.indexOf(id) !== -1;

    render() {
        const { data, order, orderBy, selected } = this.state
        const {selectable, columns, children, filtering, numSelected, ...others} = this.props
        return (
        <div>
            {selectable &&
                <EnhancedTableToolbar
                    numSelected={selected.length}
                    handleSearch={this.handleSearch}
                    value={this.searchValue}
                    unselectSelected={this.unselectSelected}
                    deleteSelected={this.deleteSelected}
                /> }
            <MuiTable >
                {selectable
                    ? <EnhancedTableHead
                        columns={columns}
                        numSelected={selected.length}
                        order={order}
                        orderBy={orderBy}
                        onSelectAllClick={this.handleSelectAllClick}
                        onRequestSort={this.handleRequestSort}
                      />
                : <TableHead>
                    <TableRow >
                        {columns.map(({dataKey, label}) =>
                            <TableCell>
                                    {label}
                            </TableCell>)}
                    </TableRow>
                </TableHead>
                }
                <TableBody>
                {data.map((item, index) => {
                    const isSelected = this.isSelected(item.id)
                    return selectable
                        ? <TableRow
                            hover
                            onClick={event => this.handleClick(event, item.id)}
                            onKeyDown={event => this.handleKeyDown(event, item.id)}
                            role="checkbox"
                            aria-checked={isSelected}
                            tabIndex="-1"
                            key={item.id}
                            selected={isSelected}
                          >
                            <TableCell checkbox>
                            <Checkbox checked={isSelected}/>
                            </TableCell>
                            {columns.map(({dataKey, cellRenderer, numeric}) =>
                                <TableCell numeric={numeric}>
                                    {(cellRenderer || this.defaultCellRenderer)({item, dataKey})}
                                </TableCell>)}
                        </TableRow>
                        : <TableRow hover>
                            {columns.map(({dataKey, cellRenderer, numeric}) =>
                                <TableCell numeric={numeric}>
                                    {(cellRenderer || this.defaultCellRenderer)({item, dataKey})}
                                </TableCell>)}
                        </TableRow>
                })}
                </TableBody>
            </MuiTable>
        </div>
        )}
}

EnchancedTable类组件(交互组件)

const columns = [
    {
        dataKey: 'deviceType',
        label:'Device Type',
        numeric: false,
    }, {
        dataKey: 'deviceID',
        label:'Device ID',
        sortable: true,
        numeric: true,
        // cellRenderer: ({item, dataKey}) =>
        //          <Button >Default</Button>,
    }, {
        dataKey: 'name',
        label: 'Name',
        sortable: true,
        numeric: false,

    },{
        dataKey: 'currentVersion',
        label: 'Current Version',
        sortable: true,
        numeric: false,
    },{
        dataKey: 'location',
        label: 'Location',
        sortable: true,
        numeric: false,
    },{
        dataKey: 'status',
        label: 'Status',
        sortable: true,
        numeric: false,
    },{
        dataKey: 'lastAliveMessage',
        label: 'Last alive message',
        sortable: true,
        numeric: false,
    }, {
        dataKey: 'action',
        label: 'Actions',
        cellRenderer: () => <SimpleMenu />,
    }]

const data = [
  { id: 1, deviceType: 'Tag', deviceID: 1, name:'Tag For sending an ', location: 'Room_104', status: 'assigned'},
  { id: 2, deviceType: 'Tag', deviceID: 2, name:'Tag For sending an ', location: 'Room_104', status: 'assigned'},
  { id: 3, deviceType: 'Tag', deviceID: 3, name:'Tag For sending an ', location: 'Room_104', status: 'assigned'},
  { id: 4, deviceType: 'Tag', deviceID: 4, name:'Tag For sending an ', location: 'Room_104', status: 'assigned'},
  { id: 5, deviceType: 'Tag', deviceID: 5, name:'Tag For sending an ', location: 'Room_104', status: 'assigned'},
]

class EnhancedTable extends {Component} {
    state = {
        selected: [],
        data,
    }

    render = () => {
        const {selected, data} = this.state

        return (
            <Paper>
                <Table
                    data={data}
                    selectable
                    columns={columns}
                    orderBy='deviceId'
                    selected={selected}
                    onSelect={selected => this.setState({selected})}
                    onDelete={items => this.setState({data: data.filter((item, index) => !items.includes(index))})}
                    onSelectAll={}
                />
            </Paper>)
    }
}

1 个答案:

答案 0 :(得分:0)

在react中实现无状态组件的最佳方法是使用recompose。您可以看到我的this答案。