我有一个对象数组,应该按用户定义的属性(在下拉列表中)进行排序。这是代码:
import React, {useState, useEffect} from 'react';
const repos = [
{
name: 'repo1',
forks_count: 5,
stargazers_count: 3,
updated_at: 12
},
{
name: 'repo2',
forks_count: 7,
stargazers_count: 2,
updated_at: 17
},
{
name: 'repo3',
forks_count: 8,
stargazers_count: 11,
updated_at: 5
}
];
function App() {
const[data, setData] = useState([]);
const[sortType, setSortType] = useState('stars');
useEffect(() => {
const sortRepos = (type) => {
const types = {
stars: 'stargazers_count',
forks: 'forks_count',
upd: 'updated_at'
};
const sortProperty = types[type];
const sorted = repos.sort((a,b) => b[sortProperty] - a[sortProperty]);
setData(sorted);
};
sortRepos(sortType);
}, [sortType]);
return (
<div className="App">
<select onChange={(e) => setSortType(e.target.value)}>
<option value='stars'>Stars</option>
<option value='forks'>Forks</option>
<option value='upd'>Updated</option>
</select>
<div >
{data.map(repo => (
<div key={repo.name}>
<div>Name {repo.name}</div>
<div>Forks {repo.forks_count}</div>
<div>Stars {repo.stargazers_count}</div>
<div>Update {repo.updated_at}</div>
</div>
))}
</div>
</div>
);
}
但是问题在于,排序后的数据在更改下拉列表中的值后会重新向后退一步。
我在做什么错?我的猜测是问题在于比较对象,因为我已经测试过在数据变量中设置原始值,并且一切正常。但是没有对象。
答案 0 :(得分:6)
问题是(间接地)您正在直接修改状态数据not allowed in React。您正在状态数组上调用sort
,对数组进行排序。您需要将其复制并排序副本。您没有及时看到更新,因为您正在使用已经具有的相同数组调用setData
,因此它忽略了该调用。
const sorted = [...repos].sort((a,b) => b[sortProperty] - a[sortProperty]);
// −−−−−−−−−−−−^^^^^^^^^^
实时示例:
const {useState, useEffect} = React;
const repos = [
{
name: 'repo1',
forks_count: 5,
stargazers_count: 3,
updated_at: 12
},
{
name: 'repo2',
forks_count: 7,
stargazers_count: 2,
updated_at: 17
},
{
name: 'repo3',
forks_count: 8,
stargazers_count: 11,
updated_at: 5
}
];
function App() {
const[data, setData] = useState([]);
const[sortType, setSortType] = useState('stars');
useEffect(() => {
const sortRepos = (type) => {
const types = {
stars: 'stargazers_count',
forks: 'forks_count',
upd: 'updated_at'
};
const sortProperty = types[type];
const sorted = [...repos].sort((a,b) => b[sortProperty] - a[sortProperty]);
setData(sorted);
};
sortRepos(sortType);
}, [sortType]);
return (
<div className="App">
<select onChange={(e) => setSortType(e.target.value)}>
<option value='stars'>Stars</option>
<option value='forks'>Forks</option>
<option value='upd'>Updated</option>
</select>
<div >
{data.map(repo => (
<div key={repo.name}>
<div>Name {repo.name}</div>
<div>Forks {repo.forks_count}</div>
<div>Stars {repo.stargazers_count}</div>
<div>Update {repo.updated_at}</div>
</div>
))}
</div>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.11.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script>