首页 > 解决方案 > React:如何在 App.js 中重新渲染状态变化的路由

问题描述

我有一个 React 应用程序,它呈现两条路由:一个 CreatorView 和一个在 App.js 下路由的 ViewerView(两者都由较小的组件组​​成)。我遇到的问题是,当我在浏览器的两个不同选项卡中打开两条路由并单击 CreatorView 中组件内的按钮时,我使用回调来更改/设置 App.js 的状态(首先我从组件到 CreatorView,然后从 CreatorView 我将状态传递给 App.js 并设置 App.js 的状态)。最后,我将 App.js 的新状态传递给 ViewerView,这是一个路由组件,因为我希望它重新渲染以显示其他内容。理论上,当我单击 CreatorView 中的按钮时,App.js 会重新渲染(由于状态更改)以及路由(CreatorView 和 ViewerView)。但是,只有 CreatorView 似乎会随着这种状态变化而重新渲染。ViewerView 没有 即使通过 App.js 更改其状态,它似乎也在更新/重新渲染。换句话说,一旦我单击另一个选项卡中的 CreatorView 中的按钮,如何使 ViewerView 重新渲染,它已经在另一个选项卡中打开。我在下面提供了我的文件层次结构和我的代码:

 ┣ elements
 ┃ ┗ CreatorControlPanel.js #contains the button which will trigger set state in App.js
 ┃ ┗ CreatorHeader.js
 ┃ ┗ ViewerControlPanel.js
 ┃ ┗ ViewerHeader.js
 ┣ views
 ┃ ┗ CreatorView.js #contains CreatorControlPanel & CreatorHeader
 ┃ ┗ ViewerView.js #contains ViewerControlPanel & ViewerHeader

应用程序.js

class App extends Component {
    constructor() {
    super()
    this.state = {
        click: false
    }
    this.setClicked = this.setClicked.bind(this)
    }
    
    setClicked() {
        this.setState({click: true})
    }
    
    render() {
        return (
            <Router>
                <Switch>
                    <Route path="/:snippetId/creator" exact render={() => ( <CreatorView clickedCallback={this.setClicked}/> )}  />
                    <Route path="/:snippetId"   render={() => ( <ViewerView clicked={this.state.click}/> )} />
                </Switch>
            </Router>
        );
    }
}

CreatorControlPanel.js

import { MyContext } from '../views/MyProvider';

class CreatorControlPanel extends Component { 
constructor(props) {
    state = {...}
    
    handleClick() {
       this.props.clickCallback();
    }

    render() {
        return(
           <Button onClick={this.handleClick}>Click me</Button>{' '}
        )
    }
}

CreatorView.js

import CreatorControlPanel from '../elements/CreatorControlPanel';

class CreatorView extends Component {
      state = { ... }

      setClicked() {
        this.props.clickedCallback();
      }

      render() {
          return(
             <CreatorControlPanel clickCallback={this.setClicked}/>/>
          )
      }
}

ViewerView.js

class ViewerView extends Component {
    
    state = {
         click: null
    }     
    
    componentDidMount() {
        this.setState({click: this.props.clicked})
    }

    render() {
      if(this.state.click === false){
        return (
            <div>hi, hello</div>
        )
      } else return (
            <div>clicked</div> #ViewerView won't re-render to display this once clicked
        )
    } 

标签: javascriptreactjs

解决方案


您可以使用use-persisted-state将视图持久化到 localStorage

import createPersistedState from 'use-persisted-state';
const useView = createPersistedState('click');

const CreatorView = () => {
  const [click, setClick] = useView(false);

  return (<div>{click}</div>)
};


   const ViewerView = () => {
      const [click, setClick] = useView(false);
    
      return (<div>{click}</div>)
   }

您的所有窗口和选项卡使用相同的键共享该状态。因此,如果您在窗口选项卡 1 的 CreatorView 中将单击设置为 true,它也会反映在窗口选项卡 2 的 ViewerView 中。

由于它使用localStorage,您可以存储一些事件,但我不建议您保存大数据。它不是为此而设计的。


推荐阅读