为 cookie 管理创建单独的反应组件
create separate react component for cookie management
我有一个组件,如果它的 prop.paramA 不同于存储在 cookie 中的 paramA 值,它就会呈现。
以下是我尝试将 cookie 管理逻辑移动到一个单独的组件中。问题是问题组件只在 showQuestion 为 false 时呈现一次,所以我永远看不到问题。
目前,我的代码如下所示
// question.js
import React from 'react';
import ToggleDisplay from 'react-toggle-display';
import {withCookies, Cookies} from 'react-cookie';
class Question extends React.Component {
static get propTypes() {
return {
cookies: instanceOf(Cookies).isRequired
}
}
constructor(props) {
super(props);
this.state = {
paramA: props.paramA,
showQuestion: props.showQuestion
};
}
componentDidMount() {
if (this.state.showQuestion) {
// do some ajax calls etc.
}
}
render() {
return (
<div id="simplequestion">
<ToggleDisplay show={this.state.showQuestion}>
<div>What is your SO profile?</div>
</ToggleDisplay>
</div>
);
}
}
export default withCookies(Question);
我写了以下 CookieManager 组件 -
// cookiemanager.js
import React from 'react';
import {withCookies, Cookies} from 'react-cookie';
class CookieManager extends React.Component {
static get propTypes() {
return {
cookies: instanceOf(Cookies).isRequired
}
}
constructor(props) {
super(props);
let propA = props.cookies.get('propA');
if (!propA || propA !== props.propA) {
props.cookies.set('propA', props.propA, { path: '/', maxAge: 604800});
console.log('changed', propA, props.propA);
props.propAChanged(true);
} else if (propA === props.propA) {
console.log('unchanged', propA, props.propA);
props.propAChanged(false);
}
}
render() {
return <div id="cookieManager"></div>;
}
}
export default withCookies(CookieManager);
以下是顶级应用
// app.js
import React from 'react';
import Question from './question';
import CookieManager from './cookiemanager';
import { CookiesProvider } from 'react-cookie';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
paramA: props.paramA,
showQuestion: false,
avoidUpdate: false
};
this.updateShowQuestion = this.updateShowQuestion.bind(this);
}
updateShowQuestion(x) {
if (this.state.avoidUpdate) {
return;
}
this.setState({
paramA: this.state.paramA,
showQuestion: x,
avoidUpdate: !this.state.avoidUpdate
});
}
componentWillUpdate(nextProps, nextState) {
if (!nextState.avoidUpdate && nextState.paramA === this.state.paramA) {
this.setState({
paramA: this.state.paramA,
showQuestion: this.state.showQuestion,
avoidUpdate: true
});
}
}
render() {
return (
<CookiesProvider>
<CookieManager paramA={this.state.paramA} ridChanged={this.updateShowQuestion}>
<Question
paramA={this.state.paramA}
showQuestion={this.state.showQuestion}/>
</CookieManager>
</CookiesProvider>
);
}
}
export default App;
您正在阅读此处的状态:
<ToggleDisplay show={this.state.showQuestion}>
但是showQuestion
只设置了一次,在构造函数中:
this.state = {
paramA: props.paramA,
showQuestion: props.showQuestion
};
当 this.props
更改时,您的组件已呈现,但您仍在读取未更新的 this.state
,因此可见输出是相同的。
我看到有两种方法可以解决这个问题:
每当道具改变时更新this.state.showQuestion
:
static getDerivedStateFromProps(nextProps, prevState) {
if(nextProps.showQuestion !== prevState.showQuestion)
return { showQuestion };
}
在render()
中,从this.props.showQuestion
读取:
<ToggleDisplay show={this.props.showQuestion}>
这种方式可能看起来更简单,但使用其他方式您可以获得对状态更改的更细粒度控制。
你错过的另一件事在这里找到:
componentWillUpdate(nextProps, nextState) {
if (!nextState.avoidUpdate && nextState.paramA === this.state.paramA) {
this.setState({
paramA: this.state.paramA,
showQuestion: this.state.showQuestion, // this line
avoidUpdate: true
});
}
}
您正在接收新道具,但您设置的是旧状态:showQuestion: this.state.showQuestion
。取而代之的是,通过新道具设置新的 showQuestion
值 - nextProps
,这样:
componentWillUpdate(nextProps, nextState) {
if (!nextState.avoidUpdate && nextState.paramA === this.state.paramA) {
this.setState({
paramA: this.state.paramA,
showQuestion: nextProps.showQuestion, // this line
avoidUpdate: true
});
}
}
我有一个组件,如果它的 prop.paramA 不同于存储在 cookie 中的 paramA 值,它就会呈现。
以下是我尝试将 cookie 管理逻辑移动到一个单独的组件中。问题是问题组件只在 showQuestion 为 false 时呈现一次,所以我永远看不到问题。
目前,我的代码如下所示
// question.js
import React from 'react';
import ToggleDisplay from 'react-toggle-display';
import {withCookies, Cookies} from 'react-cookie';
class Question extends React.Component {
static get propTypes() {
return {
cookies: instanceOf(Cookies).isRequired
}
}
constructor(props) {
super(props);
this.state = {
paramA: props.paramA,
showQuestion: props.showQuestion
};
}
componentDidMount() {
if (this.state.showQuestion) {
// do some ajax calls etc.
}
}
render() {
return (
<div id="simplequestion">
<ToggleDisplay show={this.state.showQuestion}>
<div>What is your SO profile?</div>
</ToggleDisplay>
</div>
);
}
}
export default withCookies(Question);
我写了以下 CookieManager 组件 -
// cookiemanager.js
import React from 'react';
import {withCookies, Cookies} from 'react-cookie';
class CookieManager extends React.Component {
static get propTypes() {
return {
cookies: instanceOf(Cookies).isRequired
}
}
constructor(props) {
super(props);
let propA = props.cookies.get('propA');
if (!propA || propA !== props.propA) {
props.cookies.set('propA', props.propA, { path: '/', maxAge: 604800});
console.log('changed', propA, props.propA);
props.propAChanged(true);
} else if (propA === props.propA) {
console.log('unchanged', propA, props.propA);
props.propAChanged(false);
}
}
render() {
return <div id="cookieManager"></div>;
}
}
export default withCookies(CookieManager);
以下是顶级应用
// app.js
import React from 'react';
import Question from './question';
import CookieManager from './cookiemanager';
import { CookiesProvider } from 'react-cookie';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
paramA: props.paramA,
showQuestion: false,
avoidUpdate: false
};
this.updateShowQuestion = this.updateShowQuestion.bind(this);
}
updateShowQuestion(x) {
if (this.state.avoidUpdate) {
return;
}
this.setState({
paramA: this.state.paramA,
showQuestion: x,
avoidUpdate: !this.state.avoidUpdate
});
}
componentWillUpdate(nextProps, nextState) {
if (!nextState.avoidUpdate && nextState.paramA === this.state.paramA) {
this.setState({
paramA: this.state.paramA,
showQuestion: this.state.showQuestion,
avoidUpdate: true
});
}
}
render() {
return (
<CookiesProvider>
<CookieManager paramA={this.state.paramA} ridChanged={this.updateShowQuestion}>
<Question
paramA={this.state.paramA}
showQuestion={this.state.showQuestion}/>
</CookieManager>
</CookiesProvider>
);
}
}
export default App;
您正在阅读此处的状态:
<ToggleDisplay show={this.state.showQuestion}>
但是showQuestion
只设置了一次,在构造函数中:
this.state = {
paramA: props.paramA,
showQuestion: props.showQuestion
};
当 this.props
更改时,您的组件已呈现,但您仍在读取未更新的 this.state
,因此可见输出是相同的。
我看到有两种方法可以解决这个问题:
每当道具改变时更新
this.state.showQuestion
:static getDerivedStateFromProps(nextProps, prevState) { if(nextProps.showQuestion !== prevState.showQuestion) return { showQuestion }; }
在
render()
中,从this.props.showQuestion
读取:<ToggleDisplay show={this.props.showQuestion}>
这种方式可能看起来更简单,但使用其他方式您可以获得对状态更改的更细粒度控制。
你错过的另一件事在这里找到:
componentWillUpdate(nextProps, nextState) {
if (!nextState.avoidUpdate && nextState.paramA === this.state.paramA) {
this.setState({
paramA: this.state.paramA,
showQuestion: this.state.showQuestion, // this line
avoidUpdate: true
});
}
}
您正在接收新道具,但您设置的是旧状态:showQuestion: this.state.showQuestion
。取而代之的是,通过新道具设置新的 showQuestion
值 - nextProps
,这样:
componentWillUpdate(nextProps, nextState) {
if (!nextState.avoidUpdate && nextState.paramA === this.state.paramA) {
this.setState({
paramA: this.state.paramA,
showQuestion: nextProps.showQuestion, // this line
avoidUpdate: true
});
}
}