Reputation: 1059
I want to have client side sorting that enables the user to sort by different keys. The keys are integers only.
Right now I am calling my sort function right before the map function:
.sort(function(a, b) {
return b.sortKey- a.sortKey;
}
When the user presses a button, the sortKey should change to a specified value. This is all included in a react component, not a function. I read that properties on a component should not be changed by the component itself, so how would i go about changing the sortKey on the button press?
My render function contains the two sorting options and the list:
render() {
return (
<div className="row">
<div className="col s12">
<button onClick={() => this.changeSortKey("yes")} style={{ marginRight: 5, marginTop: 5 }} className="btn">
Yes Votes
</button>
<button onClick={() => this.changeSortKey("no")} style={{ marginTop: 5 }} className="btn">
No Votes
</button>
</div>
{this.renderSurveys()}
</div>
);
}
The changeSortKey(key) function would ideally change the sortKey and then render the list anew, but I'm not sure how to render the list again, after the user has clicked.
If i just supply the sort function with a known key, the sorting works perfectly.
EDIT: Fetching the data from API
export const fetchSurveys = () => async dispatch => {
const response = await axios.get("/api/surveys");
dispatch({ type: FETCH_SURVEYS, payload: response.data });
};
EDIT: RenderSurveys helper function
renderSurveys() {
//custom helper method
return this.props.surveys
.sort(function(a, b) {
return b.yes - a.yes;
})
.map(survey => {
const data = [
{ text: "Yes", value: survey.yes },
{ text: "No", value: survey.no }
];
//reverse the array and then map over it, newest first
return (
<div className="col s6">
<div key={survey._id} className="card darken-1">
<div className="card-content">
<span className="card-title">{survey.title}</span>
<p>Sent On: {new Date(survey.dateSent).toLocaleDateString()}</p>
<p>
Last responded on:{" "}
{new Date(survey.lastResponded).toLocaleDateString()}
</p>
</div>
<div className="card-action">
<a href="#">Yes: {survey.yes}</a>
<a href="#">No: {survey.no}</a>
<BarChart width={100} height={70} data={data} />
<button
onClick={() => this.props.deleteSurvey(survey._id)}
className="btn-floating btn-large red right"
>
<i className="material-icons">clear</i>
</button>
</div>
</div>
</div>
);
});
}
Upvotes: 0
Views: 2682
Reputation: 1247
I would do as follows:
First, on your componentWillMount method I would store your votes on state.
Then, when your user clicks the button, store the votes value on a let variable and sort that variable.
Finally, update your state with the new sorted array.
This way your component will re render every time you sort your array:
componentWillMount() {
this.setState({ myArray: this.props.yourReduxStoredProp });
}
_sortList() => {
// retrieve your array from state
let myArray = this.state.myArray;
// sort the array locally
myArray.sort(function(a, b) {
return b.sortKey- a.sortKey;
});
// update the state and, because of the change it state, the component re-renders
this.setState({ myArray: myArray });
}
Remember that Redux becomes handy when you have to share data between many views, but if you are just showing data in a single view it is way more usefull to use the component state.
I would use redux to store de values on the long term and keep them stored in your app, but the state to manipulate the display of that data.
Upvotes: 1
Reputation: 24660
If you store the sorted version of your data in state, when you re-sorted and then set it to the state the component will be rendered with the new sorted array.
Upvotes: 1