尝试将类组件重写为功能组件

问题描述 投票:0回答:1

我正在尝试将类组件转换为功能组件,但遗憾的是我没有按预期工作。类组件动态呈现选择行以更改状态。如果用户选择第一行上的数据,并选择“无”以外的任何内容,则呈现第三个选择行。

我试图将其重写为一个功能组件,但是当我更改第一行select时的数据时,一切都消失了。

类组件:

import React from 'react';
import Books from './Books';

const TYPES = [
    { slug: 'title', description: 'Title' },
    { slug: 'author', description: 'Author' },
    { slug: 'editionYear', description: 'Edition Year' }
];

class BookListSorter extends React.Component {
    state = {
        sortBy: [ { author: 'asc' } ]
    };

    getSortByKeyForIndex = (index) => Object.keys(this.state.sortBy[index] || {})[0];
    getSortByValueForIndex = (index) => Object.values(this.state.sortBy[index] || {})[0];

    changeSort = (key, index) => (e) => {
        const { target } = e;
        this.setState(({ sortBy }) => {
            const type = key === 'type' ? target.value : this.getSortByKeyForIndex(index);
            const direction = key === 'direction' ? target.value : this.getSortByValueForIndex(index);
            console.log(sortBy);
            return type || direction ? sortBy.splice(index, 1, { [type]: direction }) : sortBy.splice(index, 1);
        });
    };

    filterTypes = (index) => ({ slug }) => {
        const sortByKeys = this.state.sortBy
            .slice(0, index)
            .reduce((keys, sortObj) => keys.concat(Object.keys(sortObj)[0]), []);
        return !sortByKeys.includes(slug);
    };

    render() {
        const { sortBy } = this.state;

        const lastIndex = sortBy.length - 1;
        const shouldAddNewRow = this.getSortByKeyForIndex(lastIndex) && this.getSortByValueForIndex(lastIndex);
        const rowCount = shouldAddNewRow ? sortBy.length + 1 : sortBy.length;

        return (
            <div>
                <h1>Choose sort order</h1>
                {Array.from(Array(Math.min(rowCount, TYPES.length))).map((dummy, index) => (
                    <div>
                        <select
                            defaultValue={this.getSortByKeyForIndex(index)}
                            onChange={this.changeSort('type', index)}
                        >
                            <option value="">None</option>
                            {TYPES.filter(this.filterTypes(index)).map(({ slug, description }) => (
                                <option value={slug}>{description}</option>
                            ))}
                        </select>
                        <select
                            defaultValue={this.getSortByValueForIndex(index)}
                            onChange={this.changeSort('direction', index)}
                        >
                            <option value="asc">None</option>
                            <option value="asc">Ascending</option>
                            <option value="desc">Descending</option>
                        </select>
                        <br />
                    </div>
                ))}
                <br />
                <Books order={sortBy} />
            </div>
        );
    }
}

export default BookListSorter;


功能组件:

import React, { useContext, useState } from 'react';
import OrderContext from '../context/order-context';

const TYPES = [
    { slug: 'title', description: 'Title' },
    { slug: 'author', description: 'Author' },
    { slug: 'editionYear', description: 'Edition Year' }
];

const BookListSorter = () => {
    const { dispatch } = useContext(OrderContext, []);
    const [ order, setOrder ] = useState([ { title: 'asc' } ]);

    const getSortByKeyForIndex = (index) => Object.keys(order[index] || {})[0];
    const getSortByValueForIndex = (index) => Object.values(order[index] || {})[0];

    const changeSort = (key, index) => (e) => {
        const { target } = e;
        setOrder((order) => {
            const type = key === 'type' ? target.value : getSortByKeyForIndex(index);
            const direction = key === 'direction' ? target.value : getSortByValueForIndex(index);
            console.log(order);
            return type || direction ? order.splice(index, 1, { [type]: direction }) : order.splice(index, 1);
        });
    };

    const filterTypes = (index) => ({ slug }) => {
        const sortByKeys = order.slice(0, index).reduce((keys, sortObj) => keys.concat(Object.keys(sortObj)[0]), []);
        return !sortByKeys.includes(slug);
    };

    const lastIndex = order.length - 1;
    const shouldAddNewRow = getSortByKeyForIndex(lastIndex) && getSortByValueForIndex(lastIndex);
    const rowCount = shouldAddNewRow ? order.length + 1 : order.length;
    return (
        <div>
            <h1>Choose sort order</h1>
            {Array.from(Array(Math.min(rowCount, TYPES.length))).map((dummy, index) => (
                <div>
                    <select defaultValue={getSortByKeyForIndex(index)} onChange={changeSort('type', index)}>
                        <option value="">None</option>
                        {TYPES.filter(filterTypes(index)).map(({ slug, description }) => (
                            <option value={slug}>{description}</option>
                        ))}
                    </select>
                    <select defaultValue={getSortByValueForIndex(index)} onChange={changeSort('direction', index)}>
                        <option value="asc">None</option>
                        <option value="asc">Ascending</option>
                        <option value="desc">Descending</option>
                    </select>
                    <br />
                </div>
            ))}
            <br />
        </div>
    );
};

export default BookListSorter;

javascript reactjs react-hooks
1个回答
0
投票

尝试从setOrder()中取出这个逻辑

    const changeSort = (key, index) => (e) => {
        const { target } = e;
        const type = key === 'type' ? target.value : getSortByKeyForIndex(index);
        const direction = key === 'direction' ? target.value : getSortByValueForIndex(index);
        console.log(order);
        const newOrder =  type || direction ? order.splice(index, 1, { [type]: direction }) : order.splice(index, 1);
        setOrder(newOrder);
    };
© www.soinside.com 2019 - 2024. All rights reserved.