I have an issue where I will send a user to a react-router route after login, based on the following:
... //check login browserHistory.push(self.props.destination_url); I was expecting componentDidMount to run, since this component had not been on the screen since I loaded the app, but it will not. If I click a link to it (react-router link) in the nav bar, componentDidMount does run however.
I just need to make an API call when this component comes on the screen because of a browserHistory.push(self.props.destination_url); route change. I've tried things like
<Router createElement={ (component, props) => { const { location } = props const key = `${location.pathname}${location.search}` props = { ...props, key } return React.createElement(component, props) } }/> here Component does not remount when route parameters change and it isn't working.
Here http://busypeoples.github.io/post/react-component-lifecycle/ shows "on mount", "on unmount", "on state change", or "on props changes". I'm not seeing any of those apply here. Is there a lifecycle method that will run after this browserHistory push transition? Thank you
I've been trying random lifecycle methods and componentWillUpdate does run after browserHistory.push but it runs hundreds of times, completely slowing the app down. I'd assume something I did inside it caused the nearly infinite loop:
componentWillUpdate() { console.log('it ran componentWillUpdate'); if (this.props.email) { console.log('firing off /api/userInfo'); let self = this; axios.post('/api/userInfo', {email: this.props.email}) .then(function (response) { let result = response.data.result; console.log('after calling /api/userInfo'); console.log(response); console.log(result); if (result) { self.setState({restaurant_profile: result}); } }) .catch(function (error) { console.log("Something went wrong trying to check for a user's restaurant profile"); console.log(error); }); } } On the server/client you now see the POST run hundreds of times:
Executing (default): SELECT `id`, `email`, `password`, `RestaurantId` FROM `Users` AS `User` WHERE `User`.`email` = 'fake@fake.com' LIMIT 1; Executing (default): SELECT `id`, `email`, `password`, `RestaurantId` FROM `Users` AS `User` WHERE `User`.`email` = 'fake@fake.com' LIMIT 1; Executing (default): SELECT `id`, `email`, `password`, `RestaurantId` FROM `Users` AS `User` WHERE `User`.`email` = 'fake@fake.com' LIMIT 1; Executing (default): SELECT `id`, `email`, `password`, `RestaurantId` FROM `Users` AS `User` WHERE `User`.`email` = 'fake@fake.com' LIMIT 1; ... This will work for the student's demo, but not longterm. Looking for a lifecycle method that will only run once, and that changing state is safe and won't cause infinite loop
My r dependencies look like
"react": "^15.6.1", "react-dom": "^15.6.1", "react-redux": "^5.0.6", "react-router": "^3.0.5", "react-router-dom": "^4.2.2", "react-transform-hmr": "^1.0.4", "redux": "^3.7.2", These routes are looking like
import React from "react"; import ReactDOM from "react-dom"; import { Provider } from "react-redux"; import { createStore, applyMiddleware } from "redux"; import { Router, Route, Link, IndexRoute, browserHistory } from "react-router"; import reducers from "./reducers"; import { loadConfig, getConfig } from "./config"; import Nav from "./Nav"; import LoginPage from "./containers/LoginPage"; import MapShowRestaurants from "./components/MapShowRestaurants"; import RestaurantRegistration from "./containers/RestaurantRegistration"; const createStoreWithMiddleware = applyMiddleware()(createStore); getConfig.then((config) => { loadConfig(config); ReactDOM.render( ( <Provider store={createStoreWithMiddleware(reducers)}> <Router history={browserHistory}> <Route path="/" component={Nav}> <IndexRoute component={MapShowRestaurants} /> <Route path="/login" component={LoginPage} /> <Route path="/registerRestaurant" component={RestaurantRegistration} /> </Route> </Router> </Provider> ), document.querySelector('.container')); }) .catch((err) => { console.log(err); }) Thank you
2 Answers
Answers 1
don't put API calls in a component lifecycle.
create an action
function getUserInfo(payload) { // do axios return { type: 'GET_USER_INFO', payload: result_of_your_api_call, error: false/true }; } create reducer for this action and mutate state in reducer
after that, you need to matStateToProps and mapDispatchToProps
connect(mapStateToProps, mapDispatchToProps)(YourMagicComponent) that connects your component and your redux
After that, you get a redux state in your component. For more information please read this http://redux.js.org/docs/basics/ExampleTodoList.html
Remember 1. when component initialized it hasn't any data in props except defaultProps. 2. componentDidMount doesn't know anything outside component (available only default props and props defined before component mounted) 3. if you need to do something in componentWillUpdate you need to define rules for update that's component
componentWillUpdate(nextProps) { this.setState(key: nextProps.key) } shouldComponentUpdate(nextProps, nextState) { // fix for your update if (this.state.key !== nextProps.key) { return true; } } Answers 2
@codyc4321 try self.props.router.push('/url')
0 comments:
Post a Comment