我已经创建了一个组件,该组件是表单组件的包装:
class RestaurantEdit extends React.Component {
constructor(props) {
super(props)
this.state = { waitingForRequest: false }
}
componentDidUpdate(prevProps) {
const { currentRequestState } = this.props
const { waitingForRequest } = this.state
if (
waitingForRequest &&
prevProps.currentRequestState === requestStates.PENDING &&
currentRequestState === requestStates.SUCCESS
) {
this.props.history.goBack()
this.setState({ waitingForRequest: false })
}
}
handleSubmit = (restaurantInfos, restaurantId) => {
const { editRestaurant } = this.props
const { password, ...dataWithoutPassword } = restaurantInfos
this.setState({ waitingForRequest: true })
if (password === '') {
editRestaurant(restaurantId, dataWithoutPassword)
} else {
editRestaurant(restaurantId, restaurantInfos)
}
}
handleCancel = () => {
this.props.history.goBack()
}
render() {
const { id, data = {} } = this.props
const { password, ...dataWithoutPassword } = data
return (
<RestaurantForm
id={id}
data={dataWithoutPassword}
onCancel={this.handleCancel}
onSubmit={this.handleSubmit}
isPasswordRequired={false}
/>
)
}
}
const mapStateToProps = state => ({
currentRequestState: restaurantSelectors.getRequestState(state)
})
const mapDispatchToProps = dispatch => ({
editRestaurant: (restaurantId, restaurantInfos) => {
dispatch(editRestaurantRequested(restaurantId, restaurantInfos))
}
})
export default connect(
mapStateToProps,
mapDispatchToProps
)(RestaurantEdit)
此组件安装在React路由器交换机的父级中:
<Switch>
<Route
path="/restaurants/new"
exact
component={props => (
<RestaurantCreate onSuccess={this.handleSuccess} {...props} />
)}
/>
<Route
path="/restaurants/edit"
component={props => {
const id = props.location.search.split('=')[1]
const data = currentCityRestaurants.find(resto => resto.id === id)
return <RestaurantEdit id={id} data={data} {...props} />
}}
>
</Route>
<Route
path="/restaurants"
exact
component={/* otherComponent */}
/>
</Switch>
我在这里的大问题是,当我尝试调度一个动作(例如,editRestaurant
(由mapDispatchToProps作为道具提供给RestaurantEdit
的道具)时,商店正在更新,并且使组件卸下并重新安装。
此卸载操作将阻止this.setState({ waitingForRequest: true })
中的componentDidUpdate
完成,并且waitingForRequest
始终为假
我注意到,如果我将组件作为Route
的直接子代传递,则不会进行卸载/重新安装:
<Route
path="/restaurants/edit"
exact
>
<RestaurantEdit …… />
</Route>
但是我无法使用此解决方案,因为我需要访问location
组件提供的history
和Route
。
当我将组件作为component
的道具传递到Route
时,有没有办法防止所有这些操作通过React Router卸载?
答案 0 :(得分:1)
这就是在渲染周期中使用匿名函数时发生的情况。 React不知道您的匿名函数的输出与上次渲染的输出相同,这就是为什么要卸载和重新安装组件的原因。
话虽如此,您无需使用render prop函数即可访问Route prop。它们已经作为道具传递给了您的组件。
<Route
path="/restaurants/edit"
component={RestaurantEdit}
/>
const RestaurantEdit = (props) => {
console.log(props.location, props.history)
return ...
}
答案 1 :(得分:1)
如果要在路由中渲染元素时需要一些附加功能,则需要使用render
关键字代替component
在您的示例中
<Route
path="/restaurants/edit"
component={props => {
const id = props.location.search.split('=')[1]
const data = currentCityRestaurants.find(resto => resto.id === id)
return <RestaurantEdit id={id} data={data} {...props} />
}}
>
更改component关键字以呈现并使用函数返回修改后的组件
<Route
path="/restaurants/edit"
render={ props => {
const id = props.location.search.split('=')[1]
const data = currentCityRestaurants.find(resto => resto.id === id)
return (<RestaurantEdit id={id} data={data} {...props} />)
}}
>
这可以方便地进行内联渲染和包装,而无需进行上述不必要的重新安装
https://reacttraining.com/react-router/web/api/Route/render-func