javascript - 对状态中的元素进行排序后,React 列表不会重新渲染表格

标签 javascript html reactjs

我在对表格进行排序后遇到了 React 无法渲染的问题。它似乎更新了状态变量,我正在使用 setState,我只是不知道为什么它没有显示新的更新数据。 这是我的代码

class CarRow extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            manufacturer: this.props.passedCar.manufacturer,
            model: this.props.passedCar.model,
            year: this.props.passedCar.year,
            stock: this.props.passedCar.stock,
            price: this.props.passedCar.price,
        }

        this.state.price = this.state.price.toLocaleString(undefined, {maximumFractionDigits: 2})
    }

    handleCount(value) {
        this.setState((prevState) => ({stock: prevState.stock + value}));
    }

    render() {
        return (<tr>
            <td>{this.state.manufacturer}</td>
            <td>{this.state.model}</td>
            <td>{this.state.year}</td>
            <td>{this.state.stock}</td>
            <td>${this.state.price}</td>
            <td>
                <button onClick={() =>
                    this.handleCount(1)}>
                    Increment
                </button>
            </td>
        </tr>)
    }
}


class App extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            descending: true,
            cars: [
                {
                    "manufacturer": "Toyota",
                    "model": "Rav4",
                    "year": 2008,
                    "stock": 3,
                    "price": 8500
                },

                {
                    "manufacturer": "Toyota",
                    "model": "Camry",
                    "year": 2009,
                    "stock": 2,
                    "price": 6500
                },

                {
                    "manufacturer": "Toyota",
                    "model": "Tacoma",
                    "year": 2016,
                    "stock": 1,
                    "price": 22000
                },

                {
                    "manufacturer": "Dodge",
                    "model": "Charger",
                    "year": 2013,
                    "stock": 2,
                    "price": 16000
                },

                {
                    "manufacturer": "Ford",
                    "model": "Mustang",
                    "year": 2009,
                    "stock": 1,
                    "price": 8000
                },

            ]
        };
    }

    sortCars() {
        var carsSorted = JSON.parse(JSON.stringify(this.state.cars));
        carsSorted.sort((a, b) => (this.state.descending ? b.price - a.price : a.price - b.price));
        this.setState({cars: carsSorted});
        this.setState({descending: !this.state.descending});
    }

    render() {
        return (
            <table>
                <thead>
                <tr>
                    <th>manufacturer</th>
                    <th>model</th>
                    <th>year</th>
                    <th>stock</th>
                    <th onClick={() =>
                        this.sortCars()}>price
                    </th>
                    <th>Option</th>
                </tr>
                </thead>
                <tbody>
                {this.state.cars.map((car) => {
                    return <CarRow passedCar={car}/>;
                })}
                </tbody>
            </table>
        );
    };
}

ReactDOM.render(<App/>, document.getElementById("app"))

我也尝试过为表格组件创建一个单独的项目,但它似乎不起作用。我对 react 还很陌生,对此我了解不多。

如果我能得到一些帮助,那就太好了,谢谢。

最佳答案

您需要在迭代子 CarRow 组件时为其提供一个键,以便它们能够正确重新渲染。找到可以标识行的唯一内容,并将其设置为键。例如,您可以将型号和年份放在一起:

return <CarRow key={car.model + '_' + car.year} passedCar={car}/>;

然后,当再次渲染时,它们将按照所需的正确方向排序。

class CarRow extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            manufacturer: this.props.passedCar.manufacturer,
            model: this.props.passedCar.model,
            year: this.props.passedCar.year,
            stock: this.props.passedCar.stock,
            price: this.props.passedCar.price,
        }

        this.state.price = this.state.price.toLocaleString(undefined, {maximumFractionDigits: 2})
    }

    handleCount(value) {
        this.setState((prevState) => ({stock: prevState.stock + value}));
    }

    render() {
        return (<tr>
            <td>{this.state.manufacturer}</td>
            <td>{this.state.model}</td>
            <td>{this.state.year}</td>
            <td>{this.state.stock}</td>
            <td>${this.state.price}</td>
            <td>
                <button onClick={() =>
                    this.handleCount(1)}>
                    Increment
                </button>
            </td>
        </tr>)
    }
}


class App extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            descending: true,
            cars: [
                {
                    "manufacturer": "Toyota",
                    "model": "Rav4",
                    "year": 2008,
                    "stock": 3,
                    "price": 8500
                },

                {
                    "manufacturer": "Toyota",
                    "model": "Camry",
                    "year": 2009,
                    "stock": 2,
                    "price": 6500
                },

                {
                    "manufacturer": "Toyota",
                    "model": "Tacoma",
                    "year": 2016,
                    "stock": 1,
                    "price": 22000
                },

                {
                    "manufacturer": "Dodge",
                    "model": "Charger",
                    "year": 2013,
                    "stock": 2,
                    "price": 16000
                },

                {
                    "manufacturer": "Ford",
                    "model": "Mustang",
                    "year": 2009,
                    "stock": 1,
                    "price": 8000
                },

            ]
        };
    }

    sortCars() {
        var carsSorted = JSON.parse(JSON.stringify(this.state.cars));
        carsSorted.sort((a, b) => (this.state.descending ? b.price - a.price : a.price - b.price));
        this.setState({cars: carsSorted});
        this.setState({descending: !this.state.descending});
    }

    render() {
        return (
            <table>
                <thead>
                <tr>
                    <th>manufacturer</th>
                    <th>model</th>
                    <th>year</th>
                    <th>stock</th>
                    <th onClick={() =>
                        this.sortCars()}>price
                    </th>
                    <th>Option</th>
                </tr>
                </thead>
                <tbody>
                {this.state.cars.map((car) => {
                    return <CarRow key={car.model + '_' + car.year} passedCar={car}/>;
                })}
                </tbody>
            </table>
        );
    };
}

ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>

关于javascript - 对状态中的元素进行排序后,React 列表不会重新渲染表格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66665181/

相关文章:

javascript - 防止组件卸载 - 在打开其他组件之前向用户显示通知

javascript - 如何调试 Javascript 错误?

javascript - 检查更改事件内的值 IE 7-8 与其他

javascript - 仅当值尚不存在时才将值推送到数组的最有效和干净的方法

javascript - 在不中断滚动的情况下将 div 添加到部分

javascript - 为什么只适用于 JSfiddle?

javascript - 混淆视听值得吗?

javascript - 获取 HTML 简单列表的项目

javascript - 在 react 对象中渲染链接标签

javascript - ReactJS:从 JSON 文件中提取数据时出错