React hooks - useState() 中的状态在路由更改时不会重置

Posted

技术标签:

【中文标题】React hooks - useState() 中的状态在路由更改时不会重置【英文标题】:React hooks - state in useState() is not reset when route is changed 【发布时间】:2019-08-10 18:19:40 【问题描述】:
const Create = () => 
  console.log('rerender !!')
  const [parcelType, setParcelType] = useState('paper')
  console.log('parcelType =', parcelType)

  return (
    <Container onClick=() => setParcelType('plastic')>
      <BookingList />
      <Card title="Business">
        <p>Header</p>
      </Card>
    </Container>
  )


export default Create

单击创建组件中的容器时,我想将 parcelType 状态更改为“塑料”。并且我想在路由更改时将 parcelType 状态重置为“纸张”(创建组件重新渲染)。但是当组件重新渲染状态没有设置为纸张时

更多细节:当 BookingList 组件中路由发生变化时,CreateComponent 会重新渲染

 const BookingList = props => 
  const  id  = props.match.params
  const containerStyle = useTranslateSpring('-100px', '0')

  const itemList = items.map((item, idx) => 
    const itemStyle = useTranslateSpring('-100px', '0', '0', 200 + 200 * idx)
    const url = `/booking/$item.id/create`

    return (
      <ItemContainer
        onClick=() => props.history.push(url)
        style=itemStyle
        key=item.id
        isactive=id === item.id
      >
        item.id
      </ItemContainer>
    )
  )
  return <Container style=containerStyle>itemList</Container>


export default withRouter(BookingList)

通过 routeTemplate 在路由中渲染创建组件

const Routes = () => (
 <Router basename=process.env.REACT_APP_BASE_URL>
   <> 
    <RouteTemplate
    exact
    path="/booking/:id/create"
    component=Booking.create
    title="Booking"
    />
   </>
 </Router>
)

而RouteTemplate是由PageTemplate组件包裹的渲染组件

  const RouteTemplate = props => 
  const 
    component: Component,
    title,
    query,
    isAuthenticated,
    isLanding,
    ...rest
   = props

  return (
    <Route
      ...rest
      render=matchProps =>
        isAuthenticated ? (
          <PageTemplate title=title isLanding=isLanding>
            <Component ...matchProps query=query />
          </PageTemplate>
        ) : (
          <Redirect
            to=
              pathname: '/',
              state:  from: props.location ,
            
          />
        )
      
    />
  )

【问题讨论】:

何时何地渲染创建组件 谢谢我已经在帖子中添加了更多信息。 @ShubhamKhatri 好吧,当您通过单击 ItemContainer 更改路线时,还有一个问题,例如从 booking/1/createbooking/2/create,创建组件被重新渲染。而不是我想知道的是,在 createComponent 的 Container onClick 中,您将状态更改为塑料,或者您想在使用不同 id 重新渲染容器时更改它? 我想在创建组件中单击容器时将其更改为“塑料”。并且我想在路由更改时将 parcelType 状态重置为“纸”(创建组件重新渲染) 所以换句话说,你希望组件(特别是它的状态)在路由改变后被重置,对吧? 【参考方案1】:

所以我假设您想在路由更改后重置组件的状态。

无论您使用功能组件 + 钩子或带有显式 this.state 的基于类的组件,都应该发生这种情况。这就是 React 在幕后工作的方式。

    您已经在页面上呈现了&lt;Create&gt; 一旦路由改变 &lt;Route&gt; 尝试渲染 &lt;Create&gt; 元素 React 看到已经存在 &lt;Create&gt; 元素 并尝试更新它而不是重新创建(通常更新比重新创建更有效)。这就是不重置状态的原因 - 因为它不应该为更新而重置。

有不同的处理方式。

如果这种情况发生在 react-router 的 &lt;Route&gt; 之外,我建议 use key 属性重置状态。但是对于&lt;Route&gt;,这意味着用更详细的&lt;Route path="..." render=(match) =&gt; &lt;Create match=match key=match.params.id /&gt; 替换更清晰/直截了当的&lt;Route path="..." component=Create /&gt;

因此,让我们在 props.match.params.id 更改后应用 useEffect 挂钩来重置状态:

const Create = ( match: params: id  ) =>     

  useEffect(() => 
    setParcelType('paper');
  , [id]);

应该等于基于类

state = 
  typeOfWhatEver: 'paper'
;

componentDidUpdate(prevProps) 
  if(prevProps.match.params.id !== this.props.match.params.id) 
    this.setState(
      typeOfWhatEver: 'paper'
    );
  

【讨论】:

以上是关于React hooks - useState() 中的状态在路由更改时不会重置的主要内容,如果未能解决你的问题,请参考以下文章

react使用hook——useState的坑

react的hook踩坑,useState的set方法不生效问题。

react hook介绍

react hook介绍

React Hook的注意事项--useState

React Hooks - 使用 useState 与仅使用变量