javascript - 试图将类组件重写为功能组件
问题描述
我正在尝试将类组件转换为功能组件,但不幸的是没有按我预期的那样工作。类组件动态呈现选择行以更改状态。如果用户选择第一行上的数据,并选择除“无”以外的任何内容,则呈现第三个选择行。
我试图将其重写为功能组件,但是当我更改 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;
解决方案
试着把这个逻辑从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);
};
推荐阅读
- amazon-web-services - WS - 从 worker_groups 获取实例 ID
- c++ - 在 .dll 中使用 typedef void*
- powershell - New-ADFineGrainedPasswordPolicy : 服务器不愿意处理请求
- r - r data.table 日期之间的最小值,不包括 NA
- python - 关于 Python 中的按位或运算的困惑
- wordpress - 仅在产品类别过滤器中显示与主要类别相关的类别,而不是在 woocommerce 中显示全部
- reactjs - 页面加载不到一秒钟(带有“正在加载...”),整个页面消失
- docker - curl 在 docker 容器中不起作用
- nginx - 重定向后需要配置nginx保留url参数
- mysql - 运行 mysql_secure_installation 后 mysql 的奇怪行为