React Router 4-受控组件未在交换机上解开

时间:2019-01-24 19:05:09

标签: javascript reactjs react-router-v4 react-router-dom

我正在尝试学习如何将状态从<Child/>提升到<Parent/>,并让父级控制用户交互完成子级 ,(将状态作为道具接收),即显示颜色和文字。

我能够提升状态。但是,当我在路由之间进行切换时,<Parent/>组件未重新安装,其状态与setState({})之前的设置完全相同

const cars = [
  { name: "Ferrari", cost: "$9.000", color: "red", id: 1 },
  { name: "Porsche", cost: "$8.000", color: "black", id: 2 },
  ***
];

class Dealership extends Component {
  state = {
    cars,
    isShow: {},
    correctIndex: Math.floor(Math.random() * (cars.length - 1))
  };

  handleShuffle = () => {
    this.setState({
      cars: [...this.state.cars.sort(() => Math.random() - 0.5)],
      isShow: {}
    });
  };

  handleShow = car => {
    const { isShow } = this.state;
    console.log("isShow=", isShow);

    this.setState(currentState => ({
      isShow: { ...currentState.isShow, [car]: true }
    }));
  };

  render() {
    return (
      <>
        <Navigation />
        <Routes
          state={this.state}
          shuffle={this.handleShuffle}
          handleShow={this.handleShow}
          // isShow={this.state.isShow}
        />
      </>
    );
  }
}

export default withRouter(Dealership);

如上所述, <Car/>正在接受状态作为道具,因此其用户交互可以由父级 { {1}}

<Dealership />

export default class Car extends Component { render() { const { cars, shuffle, isShow, handleShow, correctIndex } = this.props; const correctCar = cars[correctIndex]; const car = cars.map(car => ( <CarList // {...this.state} isShow={isShow[car.name]} key={car.id} car={car.name} guess={car.cost} isCorrect={correctCar.cost === car.cost} handleShow={handleShow} /> )); return ( <> <Question key={correctCar.id} guess={correctCar.cost} /> <button onClick={() => { shuffle(); }} > go again </button> <ul className="car-list">{car}</ul> </> ); } } 的摘要如下:

<CarList/>

(对我而言)奇怪的是,当我切换到拥有自己的本地状态(即// CarList.js export const CarList = ({ isShow, isCorrect, car, handleShow, guess }) => { function getColor() { if (isShow) { const showColor = isCorrect ? "green" : "red"; return showColor; } return ""; } return ( <li onClick={() => handleShow(car)} className={getColor()}> {car} <span className={isShow ? "show" : "hide"}>{guess}</span> </li> ); }; )的路由时,一切都会按预期进行(状态恢复为原始状态)

<Bike/>

这是我设置路线的方式:

import React, { useState } from "react";

export const Bike = () => {
  const [color, setColor] = useState(false);

  function ChangeColor() {
    setColor(true);
  }
  return (
    <p onClick={ChangeColor}>
      Click on the <span className={color ? "red" : " "}>Bike</span>
    </p>
  );
};

然后,如您所见,我用// Navigation.JS export const Navigation = () => ( <nav> <ul> <li> <Link to="/">home</Link> </li> <li> <Link to="/car-cost">car</Link> </li> <li> <Link to="/bike">bike</Link> </li> </ul> </nav> ); // Routes.js export const Routes = ({ state, shuffle, handleShow, isShow }) => ( <Switch> <Route path="/car-cost" render={() => ( <Car {...state} shuffle={shuffle} handleShow={handleShow} // isShow={isShow} /> )} /> <Route path="/bike" render={() => <Bike />} /> <Route path="/" component={Home} /> </Switch> ); 包裹了我的主应用程序,加上此code sandbox上当前发生的不当行为

如何在具有<BrowserRouter />的行为<Car/>的路线之间切换?即返回其原始状态。另外,我可以在这里正确地提升和控制状态吗?

1 个答案:

答案 0 :(得分:2)

这里状态被保存在父组件中。路线更改时,仅重新安装子组件。因此,父组件的状态在整个路由过程中都保持在那里。

您可以将状态保留在子组件中,这将在每次卸载后重置状态。但是,如果要提升状态并仍然重置状态,则必须在父组件中执行该操作。

更好的方法是监视父组件中的路由更改。如果路由已更改,则父组件应重置其状态。在父组件的componentDidUpdate方法中,您可以像这样跟踪路线更改并重置状态

componentDidUpdate(prevProps) {
    if (this.props.location.pathname !== prevProps.location.pathname) {
      console.log('Route change! Reset the state');
      this.setState({ isShow: {}})
    }
  }