最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React hooks - state in useState() is not reset when route is changed - Stack Overflow

programmeradmin5浏览0评论
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

I want to change parcelType state to 'plastic' when click on Container in Create ponent. and I want to reset parcelType state to 'paper' when route is change ( Create ponent re-render ). But when ponent re-render state is not set to paper

For more details: CreateComponent is re-render when route is change in BookingList ponent

 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)

Create Component is render in route by routeTemplate

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

and RouteTemplate is render Component wrapped by PageTemplate ponent

  const RouteTemplate = props => {
  const {
    ponent: 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 },
            }}
          />
        )
      }
    />
  )
}
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

I want to change parcelType state to 'plastic' when click on Container in Create ponent. and I want to reset parcelType state to 'paper' when route is change ( Create ponent re-render ). But when ponent re-render state is not set to paper

For more details: CreateComponent is re-render when route is change in BookingList ponent

 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)

Create Component is render in route by routeTemplate

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

and RouteTemplate is render Component wrapped by PageTemplate ponent

  const RouteTemplate = props => {
  const {
    ponent: 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 },
            }}
          />
        )
      }
    />
  )
}
Share Improve this question edited Mar 20, 2019 at 7:51 skyboyer 23.7k7 gold badges62 silver badges71 bronze badges asked Mar 20, 2019 at 5:46 sarin udompanitsarin udompanit 731 gold badge1 silver badge5 bronze badges 5
  • When and where do you render Create ponent – Shubham Khatri Commented Mar 20, 2019 at 5:57
  • Thank you I already add more information in post. @ShubhamKhatri – sarin udompanit Commented Mar 20, 2019 at 6:20
  • okay so one more question when you change the route by clicking on ItemContainer, from say booking/1/create to booking/2/create the create ponent is re-rendered. and not what I want to know is that in createComponent's Container onClick you change the state to plastic or you want to change it when the container is re-rendered with different id? – Shubham Khatri Commented Mar 20, 2019 at 6:27
  • I want to change it to 'plastic' when click on Container in Create ponent. and I want to reset parcelType state to 'paper' when route is change ( Create ponent re-render ) – sarin udompanit Commented Mar 20, 2019 at 6:37
  • so in other words you want ponent(its state particularly) be reset once route is changed, right? – skyboyer Commented Mar 20, 2019 at 6:49
Add a ment  | 

1 Answer 1

Reset to default 15

So I assume you want to reset ponent's state once route is changed.

This should happen wherever you use functional ponent + hooks or class-based ponent with explicit this.state. It's how React works under the hood.

  1. You already have <Create> rendered at the page
  2. Once route is changed <Route> tries to render <Create> element
  3. React sees there is already existing <Create> element and tries to update that instead of re-creating(typically update is much more efficient than re-creating). That's why state is not reset - since it should not reset for updates.

There are different way to handle that.

If such a case happen outside react-router's <Route> I'd suggest use key prop to reset state. But for <Route> it would mean replacing more clear/straightforward <Route path="..." ponent={Create} /> with more verboose <Route path="..." render={({match}) => <Create match={match} key={match.params.id} />}

So instead let's apply useEffect hook to reset state once props.match.params.id is changed:

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

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

That should be equal to class-based

state = {
  typeOfWhatEver: 'paper'
};

ponentDidUpdate(prevProps) {
  if(prevProps.match.params.id !== this.props.match.params.id) {
    this.setState({
      typeOfWhatEver: 'paper'
    });
  }
}
发布评论

评论列表(0)

  1. 暂无评论