路线更改时重置组件的内部状态

时间:2018-01-31 05:33:37

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

我正在使用react-router-v4和react 16。

当用户转到不同的路线或回到同一路线时,我想重置组件的内部状态。路由更改应该破坏组件的内部状态,但它不会。当路由发生变化时,我甚至找不到通知组件的方法,因为它是嵌套组件而不是Route组件的直接渲染。请帮忙。

这是代码或live codepen example -

const initialProductNames = {
    names: [
        { "web applications": 1 },
        { "user interfaces": 0 },
        { "landing pages": 0 },
        { "corporate websites": 0 }
    ]
};

export class ProductNames extends React.Component {

state = {
    ...initialProductNames
};

animProductNames = () => {
    const newArray = [...this.state.names];
    let key = Object.keys(newArray[this.count])[0];
    newArray[this.count][key] = 0;

    setTimeout(() => {
        let count = this.count + 1;

        if (this.count + 1 === this.state.names.length) {
            this.count = 0;
            count = 0;
        } else {
            this.count++;
        }

        key = Object.keys(newArray[count])[0];
        newArray[count][key] = 1;
        this.setState({ names: newArray });
    }, 300);
};

count = 0;

componentDidMount() {
    this.interval = setInterval(() => {
        this.animProductNames();
    }, 2000);
}

componentWillUnmount() {
    clearInterval(this.interval);
}

componentWillReceiveProps(nextProps) {
    console.log(nextProps.match);
    if (this.props.match.path !== nextProps.match.path) {
        this.setState({ ...initialProductNames });
        this.count = 0;
    }
}

render() {
    return (
        <section className="home_products">
            <div className="product_names_container">
                I design & build <br />
                {this.createProductNames()}
            </div>
        </section>
    );
}

createProductNames = () => {
    return this.state.names.map(nameObj => {
        const [name] = Object.keys(nameObj);
        return (
            <span
                key={name}
                style={{ opacity: nameObj[name] }}
                className="product_names_anim">
                {name}
            </span>
        );
    });
};
}

3 个答案:

答案 0 :(得分:2)

您可以在路径更改上使用侦听器作为this previous question上的示例,并且您可以添加一个函数来更新主状态。

for f in `find . -maxdepth 1 -type f`; do echo `basename $f`; sed -i.bak "1 i `basename $f`\t`basename $f`\t`basename $f`" $f; done

答案 1 :(得分:1)

我得到了解决方案。我没有放弃理解为什么状态property initializer没有重置/初始化重新安装。我认为它只会初始化一次,而不是每次路线更改] -

我想知道如何在路线更改时重置组件的状态。但事实证明,你没有必要。每个路由呈现特定组件。路由更改时,将卸载所有其他组件,并且还会销毁这些组件的所有状态。 但请看我的代码。我使用es7 + property initializer来声明状态,计数。这就是为什么当组件在路线上重新安装时状态没有再次重置/初始化。

要修复它,我所做的就是把状态,initialProductNames,count;所有这些都进入了constructor。而现在它的工作非常完美。

现在每个坐骑上的新状态并重新安装!

答案 2 :(得分:1)

问题不是状态,而是初始产品名称。属性初始值设定项是一种糖语法,实际上与创建构造函数并将代码移入构造函数相同。问题在于initialProductNames,它是在组件外部创建的,也就是说,整个系统只能创建一次。

要为initialProductNames的任何实例创建新的ProductNames,请执行以下操作:

export class ProductNames extends React.Component {

  initialProductNames = {
    names: [
        { "web applications": 1 },
        { "user interfaces": 0 },
        { "landing pages": 0 },
        { "corporate websites": 0 }
    ]
  };

  state = {
    ...this.initialProductNames
  };

  // more code

  componentWillReceiveProps(nextProps) {
    console.log(nextProps.match);
    if (this.props.match.path !== nextProps.match.path) {
        this.setState({ ...this.initialProductNames });
        this.count = 0;
    }
  }

下面是一个示例,显示每次重新安装时总是重新创建statehttps://codesandbox.io/s/o7kpy792pq

class Hash {
  constructor() {
    console.log("Hash#constructor");
  }
}

class Child extends React.Component {
  state = {
    value: new Hash()
  };

  render() {
    return "Any";
  }
}

class App extends React.Component {
  state = {
    show: true
  };
  render() {
    return (
      <div className="App">
        <button
          type="button"
          onClick={() =>
            this.setState({
              show: !this.state.show
            })
          }
        >
          Toggle
        </button>
        {this.state.show && <Child />}
      </div>
    );
  }
}