So I am trying to sort alphabetically an array of objects nondestructively by using state, so I can also return the array back to its original arrangement. I've tried quite a few ways of copying the original array into a new array to sort: JSON methods to carry a deep copy of this.props.getDaycare.toddlers
:
constructor(){
super()
this.state = {
newArray: []
}
}
sort = () => {
let initialArray = this.props.getDaycare.toddlers
let copiedInitialArray = JSON.parse(JSON.stringify(initialArray));
console.log(copiedInitialArray)
this.setState({
newArray: copiedInitialArray.sort((t,u) =>{
if (t.name < u.name) {return -1;}
if (t.name > u.name) {return 1;}
return 0;
})
})
}
That didn't seem to work. It did not update the DOM at all, but it did in the console (alphabetically) when I clicked the sort button
0: {id: 84, name: 'Jared Leno', birthday: '2019-09-02', contact: 'Poppy Roberts', phone: 7605551919, …}
1: {id: 88, name: 'Massimo Gandolfini', birthday: '2019-01-06', contact: 'Poppy Roberts', phone: 7605551919, …}
2: {id: 87, name: 'Rosie Perez', birthday: '2018-12-22', contact: 'Poppy Roberts', phone: 7605559091, …}
3: {id: 80, name: 'Samantha Madison', birthday: '2019-01-06', contact: 'Olusoji Akinremi', phone: 7605551919, …}
4: {id: 90, name: 'Sara Waters', birthday: '2018-12-22', contact: 'Jessica Smith', phone: 7605559091, …}
5: {id: 83, name: 'Serena Williams', birthday: '2019-01-06', contact: 'Sara Reynolds', phone: 7605551919, …}
length: 6
[[Prototype]]: Array(0)
I've tried the shallow copying methods as well such as spread
, slice
, from
. Noting but the same result of not updating the DOM but outputting in the console. I've looked everywhere online for this specific issue and I haven't seen any example showing how to effectively deep copy an array of objects for sorting. All the examples were destructive to the original array.
I'm wondering is there any way at all? please help.
Array#slice
method. You don't need a deep copy since the values in React are supposed to be immutable.render
method.render
phase/function.Like this:
const cmp = (a, b) => (a > b) - (a < b);
class SortedList extends React.Component {
constructor(props) {
super(props)
this.state = {
sort: { field: 'name', descending: false },
};
}
render() {
const { field, descending } = this.state.sort;
const mul = descending ? -1 : 1;
const items = this.props.items.slice();
items.sort((a, b) => mul * cmp(a[field], b[field]));
return (
<ul>
{items.map(({id, name}) => <li key={id}>{name}</li>)}
</ul>
);
}
}
In react, you should think of what renders as a function of props
and state
.
So there is no need to set the sorted array to state, only the sortType
, sortDirection
, and other factors that might play a part in how the list is sorted.
const List = ({ data }) => {
const [sortType, setSortType] = useState("name"); //name | birthday | contact
const [sortDirection, setSortDirection] = useState("ASC"); //ASC | DESC
const sortBy = (a, b) => {
if (sortDirection === "ASC") {
return (a[sortType] > b[sortType]) - (a[sortType] < b[sortType]);
}
return (b[sortType] > a[sortType]) - (b[sortType] < a[sortType]);
};
const handleChange = (e) => {
const { value, name } = e.target;
if (name === "sortType") {
setSortType(value);
}
if (name === "sortDirection") {
setSortDirection(value);
}
};
return (
<div>
<h2>List</h2>
<form onChange={handleChange}>
<fieldset>
<legend>Sort by</legend>
<label>
Name
<input
type="radio"
name="sortType"
value="name"
defaultChecked={true}
/>
</label>
<label>
Birthday
<input type="radio" name="sortType" value="birthday" />
</label>
<label>
Contact
<input type="radio" name="sortType" value="contact" />
</label>
</fieldset>
<fieldset>
<legend>Direction</legend>
<label>
Ascending
<input
type="radio"
name="sortDirection"
value="ASC"
defaultChecked={true}
/>
</label>
<label>
Descending
<input type="radio" name="sortDirection" value="DESC" />
</label>
</fieldset>
</form>
<ul>
{data.sort(sortBy).map((d, i) => (
<ListItem data={d} key={i} />
))}
</ul>
</div>
);
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.