Reputation: 47
Can you help me with React.js history.push function?
I have a icon which can be pressed. The onClick calls handleRemoveFavourite function which filters out the current item from localStrorage and sets the updated string to storage. This works fine.
After the storage update is done the program should reroute the user to the root page /favourites. The reroute works well in the bottom example. But how to do this in the handleRemoveFavourites function?
This is the code I would like to have
handleRemoveFavourite = () => {
const { name } = this.props.workout;
let savedStorage = localStorage.saved.split(",");
let cleanedStorage = savedStorage.filter(function(e) {
return e !== name;
});
localStorage.setItem("saved", cleanedStorage.toString());
history.push("/favourites")
};
renderHeartIcon = () => {
return (
<Route
render={({ history }) => (
<Rating
icon="heart"
defaultRating={1}
maxRating={1}
onClick={this.handleRemoveFavourite}
/>
)}
/>
);
};
The rerouting works fine with just this:
renderHeartIcon = () => {
return (
<Route
render={({ history }) => (
<Rating
key={1}
icon="heart"
defaultRating={1}
maxRating={1}
size="large"
onClick={() => history.push("/favourites")}
/>
)}
/>
);
};
The whole component looks like this:
import React from "react";
import {
Container,
Grid,
Icon,
Label,
Table,
Header,
Rating,
Segment
} from "semantic-ui-react";
import { Link, Route } from "react-router-dom";
export default class WorkoutComponent extends React.PureComponent {
renderChallengeRow = workouts => {
let { reps } = this.props.workout;
reps = reps.split(",");
return workouts.map((item, i) => {
return (
<Table.Row key={item.id}>
<Table.Cell width={9}>{item.name}</Table.Cell>
<Table.Cell width={7}>{reps[i]}</Table.Cell>
</Table.Row>
);
});
};
handleRemoveFavourite = () => {
const { name } = this.props.workout;
let savedStorage = localStorage.saved.split(",");
let cleanedStorage = savedStorage.filter(function(e) {
return e !== name;
});
localStorage.setItem("saved", cleanedStorage.toString());
// history.push("/favourites");
};
renderHeartIcon = () => {
return (
<Route
render={({ history }) => (
<Rating
key={1}
icon="heart"
defaultRating={1}
maxRating={1}
size="large"
onClick={this.handleRemoveFavourite}
/>
)}
/>
);
};
render() {
const { name, workouts } = this.props.workout;
const url = `/savedworkout/${name}`;
return (
<Grid.Column>
<Segment color="teal">
<Link to={url}>
<Header as="h2" to={url} content="The workout" textAlign="center" />
</Link>
<Table color="teal" inverted unstackable compact columns={2}>
<Table.Body>{this.renderChallengeRow(workouts)}</Table.Body>
</Table>
<br />
<Container textAlign="center">
<Label attached="bottom">{this.renderHeartIcon()}</Label>
</Container>
</Segment>
<Link to="/generate">
<Icon name="angle double left" circular inverted size="large" />
</Link>
</Grid.Column>
);
}
}
Upvotes: 0
Views: 1449
Reputation: 137
Changing to this.props.history.push("/favourites");
should works.
EDITED
Is your component inside a Route? If so, this.props.history
will works. I tested changing your class to run on my project.
import React from 'react';
import ReactDOM from 'react-dom';
import {
Container,
Grid,
Icon,
Label,
Table,
Header,
Rating,
Segment
} from "semantic-ui-react";
import { Link, Route, BrowserRouter as Router } from "react-router-dom";
export default class WorkoutComponent extends React.Component {
static defaultProps = {
workout: {
reps: "1,2,3,4",
workouts: []
},
}
renderChallengeRow = workouts => {
let { reps } = this.props.workout;
reps = reps.split(",");
return workouts.map((item, i) => {
return (
<Table.Row key={item.id}>
<Table.Cell width={9}>{item.name}</Table.Cell>
<Table.Cell width={7}>{reps[i]}</Table.Cell>
</Table.Row>
);
});
};
handleRemoveFavourite = () => {
const { name } = this.props.workout;
//let savedStorage = localStorage.saved.split(",");
// let cleanedStorage = savedStorage.filter(function(e) {
// return e !== name;
// });
// localStorage.setItem("saved", cleanedStorage.toString());
this.props.history.push("/favourites");
};
renderHeartIcon = () => {
return (
<Route
render={({ history }) => (
<Rating
key={1}
icon="heart"
defaultRating={1}
maxRating={1}
size="large"
onClick={this.handleRemoveFavourite}
/>
)}
/>
);
};
render() {
console.log(this.props)
const { name, workouts } = this.props.workout;
const url = `/savedworkout/${name}`;
return (
<Grid.Column>
<Segment color="teal">
<Link to={url}>
<Header as="h2" to={url} content="The workout" textAlign="center" />
</Link>
<Table color="teal" inverted unstackable compact columns={2}>
<Table.Body>{this.renderChallengeRow(workouts)}</Table.Body>
</Table>
<br />
<Container textAlign="center">
<Label attached="bottom">{this.renderHeartIcon()}</Label>
</Container>
</Segment>
<Link to="/generate">
<Icon name="angle double left" circular inverted size="large" />
</Link>
</Grid.Column>
);
}
}
ReactDOM.render(
<Router>
<Route path="/" component={ WorkoutComponent }/>
</Router>, document.getElementById('root'));
Upvotes: 0
Reputation: 4537
The problem you are facing is, you are providing <Route>
with the history prop, so that it is propagated on the component function call. But you are not propagating it to the handleRemoveFavourite
function.
You'll need to wrap this. handleRemoveFavourite
in an anonymous function call. Like
onClick={() => this.handleRemoveFavourite(history)}
and then accept it as a valid argument in your function
handleRemoveFavourite = (history) => {...}
that should solve it
Upvotes: 1
Reputation: 336
Since you are using react-router
you can use withRouter
to achive this.
import { withRouter } from 'react-router-dom'
Wrap the with class name with withRouter
.
Like this:
instead of doing like this:
export default class App .....
Separate this like:
class App ...
At the end of the line:
export default withRouter(App)
Now you can use like this:
handleRemoveFavourite = () => {
const { name } = this.props.workout;
let savedStorage = localStorage.saved.split(",");
let cleanedStorage = savedStorage.filter(function(e) {
return e !== name;
});
localStorage.setItem("saved", cleanedStorage.toString());
this.props.history.push("/favourites");
};
You can remove Route
from renderHearIcon()
:
renderHeartIcon = () => {
return (
<Rating
key={1}
icon="heart"
defaultRating={1}
maxRating={1}
size="large"
onClick={this.handleRemoveFavourite}
/>
);
};
Upvotes: 2
Reputation: 1050
onClick={this.handleRemoveFavourite}
=>
onClick={()=>this.handleRemoveFavourite(history)}
handleRemoveFavourite = () => {
=>
handleRemoveFavourite = (history) => {
Upvotes: 1