So I think this question has been asked a couple of times but not sure if it's been asked appropriately. Here's what I'm going through -- I have a route that is the following:
<Route exact path={RoutePaths.PROPOSAL_ID} component={ReviewProposalView} />
The value of RoutePaths.PROPOSAL_ID
is /proposal/:id
Inside of ReviewProposalView
, I have the following componentDidMount()
and render()
methods:
class ReviewProposalView extends Component<Props, State> {
state = {
redirect: false,
redirectTo: '',
currentProposalIdIndex: // whatever current value,
proposalIds: this.props.location.state.proposalIds,
proposalMap: this.props.location.state.proposalMap,
currentProposal: null
}
componentDidMount () {
const {location} = this.props
parseValueFromKeyInQueryString({queryString: location.search, key: 't'}, {
noValueFound: () => {
this.setState({
redirect: true,
redirectTo: RoutePaths.NOT_FOUND
})
},
valueFound: (type: string) => {
const {proposalMap} = this.state
const proposalId = // ...assume we got this from pathname
this.setState({
currentProposal: proposalMap[proposalId]
})
}
})
}
_confirmMatch = (confirmedProposal: Proposal) => {
// store data on confirmedProposal
// get next proposalId from this.state.proposalIds list
const nextProposal = proposalMap[nextProposalId]
this.setState({
redirect: true,
redirectTo: {
pathname: `${RoutePaths.PROPOSAL}/${nextProposal.id}`,
search: `?t=${nextProposal.type}`,
state: {
currentProposalIdIndex: nextProposalIndex,
proposalIds,
proposalMap
}
}
})
}
render () {
const {currentProposal, redirect, redirectTo} = this.state
if (redirect) {
return <Redirect push to={redirectTo} />
}
const ProposalComponent = ProposalComponentMap[currentProposal.type]
return (
<div>
<h1>Review Proposals Page</h1>
<ProposalComponent {...this.props} key={currentProposal.id} proposal={currentProposal}
confirmProposal={this._confirmProposal} />
</div>
)
}
}
// ====================================
const ProposalComponentMap = {
'PRODUCT': ProductProposalView
'SERVICE': ServiceProposalView
}
The experience that this is creating is the user goes through a list of proposals and will either Accept or Reject the proposal. There are two different kinds of proposals (ProductProposalView
or ServiceProposalView
) that the user can interact with within this parent ReviewProposalView
. The appropriate view gets rendered depending on the type of proposal we're dealing with.
Every time an Accept or Reject confirmation is made on a proposal, I want to redirect the user to the next proposal in the queue and push a new URL in the browser history stack so that I can get Back button behavior for free.
So if we start at https://myreactapp.com/proposal/id1
, my ReviewProposalView
goes through the entire lifecycle hitting componentDidMount
at the end with no problem. My desire is that when the user goes to https://myreactapp.com/proposal/id2
as a result of confirming a proposal and getting redirected via <Redirect />
, I want the entire lifecycle of the component to repeat from the beginning and to run through the logic in componentDidMount
again -- essentially promoting a characteristic of immutability with a fresh instance/start.
What I currently have does not accomplish this because the ReviewProposalView
is already mounted when you hit the 2nd URL. My instincts tell me that how I've structured my components is wrong and I'm fundamentally misunderstanding something about the React Component lifecycles when they are coupled with <Route />
. Any and all guidance is super appreciated.