React:如何在App.js中重新呈现状态更改的路由



我有一个React应用程序,它呈现两个路由:在app.js下路由的CreatorView和ViewerView(都由较小的组件组成(。我遇到的问题是,当我在浏览器的两个不同选项卡中打开两个路由,并在CreatorView中单击组件内部的一个按钮时,我使用回调来更改/设置App.js的状态(首先我将组件的状态传递给CreatorView,然后从CreatorView将状态传递给App.js并设置App.jss的状态(,这是一个路由组件,因为我希望它重新渲染以显示其他内容。理论上,当我点击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

App.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>
);
}
}

创建者控制面板.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
)
} 

您可以使用持久化状态将视图持久化到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的"创建者视图"中将Click设置为true,则它也将反映在窗口选项卡2的"查看器视图"中。

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

你不能用简单的方式做到这一点,因为当你在不同的选项卡中打开项目时,它们的行为就像不同的实例,所以你不能更新一个实例,也不能看到其他实例中的更改。

要实现这一点,您可以使用WebSocket。

最新更新