如何获取 React 应用程序的状态?
How to get the state of a React app?
所以,我已经构建了这个具有一些状态的 React 应用程序。我想知道那个状态是什么,所以我可以将它保存到 localStorage
并让状态从一个会话转移到另一个会话。基本上,该应用程序非常复杂,我不希望人们失去他们的 "place" 只是因为关闭它并稍后再次打开它。
虽然通读了 React 文档,但我没有看到 任何内容 提到从 React 外部 访问组件的状态。
这可能吗?
我认为您的问题的解决方案真正在于您的应用程序的建模方式。
理想情况下,您需要的(取决于复杂性)是一个 (flux
/redux
) 存储,您可以在该存储上订阅更改,如果有差异,则将其保存到 localStorage
.
然后您需要确定一种方法 bootstrap 将此数据放入您的单一商店。
他们 API 本身(据我所知)并不能专门做你想做的事。
不要尝试从 React 外部获取状态——将状态从 React 传递到任何需要的地方。
在你的情况下,我会执行此 componentDidUpdate。
var SampleRootComponent = React.createClass({
componentDidUpdate: function() {
localStorage.setItem(JSON.stringify(this.state))
}
})
你说得对,没有办法从外部获取状态;你必须从 React 中设置它。但是没有理由认为这是一件坏事——如果您需要将信息传递给其他东西,只需从 React 内部调用一个外部函数,如图所示。没有功能丢失。
永远不要尝试从组件获取状态,因为组件应该始终代表而不是自己生成状态。不要询问组件的状态,而是询问状态本身。
话虽这么说,我肯定明白你的意思。在谈论 React 时,术语 "state" 似乎确实非常模棱两可。
I don't see anything that references accessing a component's state
from outside of React.
一劳永逸,区别在于:
- 本地状态,不应持久化:
this.state
、this.setState
等。 本地状态只存在于组件中,一旦组件死亡,本地状态就会消失。
- 全局状态,可持久化:
this.props.passedState
。 全局状态只传递给组件,不能直接修改。视图层将根据它通过的任何全局状态进行调整。
或者简单地说:
this.state
表示本地状态,不会持久化。
this.props.state
表示通过状态,可以持久化,我们只是不知道,我们不关心。
示例
下面的例子使用了 Babel 的东西 stage-1 Preset
React 就是提供数据结构的显示表示。假设我们有以下对象可以直观地表示:
let fixtures = {
people: [
{
name: "Lukas"
},
{
name: "fnsjdnfksjdb"
}
]
}
我们有一个 App
组件,它为 people
数组中的每个条目呈现 Person
个组件。
import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
class Person extends Component {
static propTypes = {
name: PropTypes.string.isRequired
}
render() {
return (
<li>
<input type="text" value={this.props.name} />
</li>
);
}
}
class App extends Component {
static propTypes = {
people: PropTypes.array.isRequired
}
render() {
let people = this.people.map(person => {
<Person name={person.name} />
});
return (
<ul>
{people}
</ul>
);
}
}
ReactDOM.render(
<App people={fixtures} />,
document.getElementById('yourid')
);
现在,我们将实现焦点功能。有 2 个选项:
- 我们不关心用户上次使用该应用时关注的是哪个人,所以我们使用本地状态。
- 我们确实关心用户上次使用该应用程序时关注的是哪个人,因此我们使用全局状态。
选项 1
任务很简单。只需调整 People
组件,使其在焦点改变后知道(并重新呈现)。不会改变原有的数据结构,只关注组件是否被关注的信息
只是客户端信息,一旦客户端 closed/reset/whatever 就会丢失。
状态是本地的:我们使用 component.setState 将更改分派到本地状态
class Person extends Component {
static propTypes = {
name: PropTypes.string.isRequired
}
constructor(...args) {
super(...args);
this.state = {
isFocused: false
}
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
}
static propTypes = {
name: PropTypes.string.isRequired
}
onFocus() {
this.setState({
isFocused: true;
});
}
onBlur() {
this.setState({
isFocused: false;
});
}
render() {
let borderColor = this.state.isFocused ? '#ff0' : '#000';
style = {
border: `1px solid ${borderColor}`
}
return (
<li>
<input
style={style}
type="text"
value={this.props.name}
onFocus={this.onFocus}
onBlur={this.onBlur}
/>
</li>
);
}
}
选项 2
我们实际上想要将焦点元素持久化到我们拥有的任何存储(例如后端),因为我们关心最后的状态。 状态是全局的:React 组件仅接收道具 "state",甚至是元素是否聚焦等细粒度信息。 持久化并将全局状态提供给应用程序,它会相应地运行。
function setFocus(index) {
fixtures.people[index].isFocused = true;
render();
}
function clearFocus(index) {
fixtures.people[index].isFocused = false;
render();
}
function render() {
ReactDOM.render(
<App people={fixtures} />,
document.getElementById('yourid')
);
}
class Person extends Component {
static propTypes = {
name: PropTypes.string.isRequired,
isFocused: PropTypes.bool,
index: PropTypes.number.isRequired
}
static defaultProps = {
isFocused: false
}
constructor(...args) {
super(...args);
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
}
static propTypes = {
name: PropTypes.string.isRequired
}
onFocus() {
setFocus(this.props.index);
}
onBlur() {
clearFocus(this.props.index);
}
render() {
let borderColor = this.props.isFocused ? '#ff0' : '#000';
style = {
border: `1px solid ${borderColor}`
}
return (
<li>
<input
style={style}
type="text"
value={this.props.name}
onFocus={this.onFocus}
onBlur={this.onBlur}
/>
</li>
);
}
}
class App extends Component {
static propTypes = {
people: PropTypes.array.isRequired
}
render() {
let people = this.people.map((person, index) => {
<Person name={person.name} index={index} isFocused={person.isFocused} />
});
return (
<ul>
{people}
</ul>
);
}
}
render();
所以,我已经构建了这个具有一些状态的 React 应用程序。我想知道那个状态是什么,所以我可以将它保存到 localStorage
并让状态从一个会话转移到另一个会话。基本上,该应用程序非常复杂,我不希望人们失去他们的 "place" 只是因为关闭它并稍后再次打开它。
虽然通读了 React 文档,但我没有看到 任何内容 提到从 React 外部 访问组件的状态。
这可能吗?
我认为您的问题的解决方案真正在于您的应用程序的建模方式。
理想情况下,您需要的(取决于复杂性)是一个 (flux
/redux
) 存储,您可以在该存储上订阅更改,如果有差异,则将其保存到 localStorage
.
然后您需要确定一种方法 bootstrap 将此数据放入您的单一商店。
他们 API 本身(据我所知)并不能专门做你想做的事。
不要尝试从 React 外部获取状态——将状态从 React 传递到任何需要的地方。
在你的情况下,我会执行此 componentDidUpdate。
var SampleRootComponent = React.createClass({
componentDidUpdate: function() {
localStorage.setItem(JSON.stringify(this.state))
}
})
你说得对,没有办法从外部获取状态;你必须从 React 中设置它。但是没有理由认为这是一件坏事——如果您需要将信息传递给其他东西,只需从 React 内部调用一个外部函数,如图所示。没有功能丢失。
永远不要尝试从组件获取状态,因为组件应该始终代表而不是自己生成状态。不要询问组件的状态,而是询问状态本身。
话虽这么说,我肯定明白你的意思。在谈论 React 时,术语 "state" 似乎确实非常模棱两可。
I don't see anything that references accessing a component's state from outside of React.
一劳永逸,区别在于:
- 本地状态,不应持久化:
this.state
、this.setState
等。 本地状态只存在于组件中,一旦组件死亡,本地状态就会消失。 - 全局状态,可持久化:
this.props.passedState
。 全局状态只传递给组件,不能直接修改。视图层将根据它通过的任何全局状态进行调整。
或者简单地说:
this.state
表示本地状态,不会持久化。this.props.state
表示通过状态,可以持久化,我们只是不知道,我们不关心。
示例
下面的例子使用了 Babel 的东西 stage-1 Preset
React 就是提供数据结构的显示表示。假设我们有以下对象可以直观地表示:
let fixtures = {
people: [
{
name: "Lukas"
},
{
name: "fnsjdnfksjdb"
}
]
}
我们有一个 App
组件,它为 people
数组中的每个条目呈现 Person
个组件。
import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
class Person extends Component {
static propTypes = {
name: PropTypes.string.isRequired
}
render() {
return (
<li>
<input type="text" value={this.props.name} />
</li>
);
}
}
class App extends Component {
static propTypes = {
people: PropTypes.array.isRequired
}
render() {
let people = this.people.map(person => {
<Person name={person.name} />
});
return (
<ul>
{people}
</ul>
);
}
}
ReactDOM.render(
<App people={fixtures} />,
document.getElementById('yourid')
);
现在,我们将实现焦点功能。有 2 个选项:
- 我们不关心用户上次使用该应用时关注的是哪个人,所以我们使用本地状态。
- 我们确实关心用户上次使用该应用程序时关注的是哪个人,因此我们使用全局状态。
选项 1
任务很简单。只需调整 People
组件,使其在焦点改变后知道(并重新呈现)。不会改变原有的数据结构,只关注组件是否被关注的信息
只是客户端信息,一旦客户端 closed/reset/whatever 就会丢失。
状态是本地的:我们使用 component.setState 将更改分派到本地状态
class Person extends Component {
static propTypes = {
name: PropTypes.string.isRequired
}
constructor(...args) {
super(...args);
this.state = {
isFocused: false
}
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
}
static propTypes = {
name: PropTypes.string.isRequired
}
onFocus() {
this.setState({
isFocused: true;
});
}
onBlur() {
this.setState({
isFocused: false;
});
}
render() {
let borderColor = this.state.isFocused ? '#ff0' : '#000';
style = {
border: `1px solid ${borderColor}`
}
return (
<li>
<input
style={style}
type="text"
value={this.props.name}
onFocus={this.onFocus}
onBlur={this.onBlur}
/>
</li>
);
}
}
选项 2
我们实际上想要将焦点元素持久化到我们拥有的任何存储(例如后端),因为我们关心最后的状态。 状态是全局的:React 组件仅接收道具 "state",甚至是元素是否聚焦等细粒度信息。 持久化并将全局状态提供给应用程序,它会相应地运行。
function setFocus(index) {
fixtures.people[index].isFocused = true;
render();
}
function clearFocus(index) {
fixtures.people[index].isFocused = false;
render();
}
function render() {
ReactDOM.render(
<App people={fixtures} />,
document.getElementById('yourid')
);
}
class Person extends Component {
static propTypes = {
name: PropTypes.string.isRequired,
isFocused: PropTypes.bool,
index: PropTypes.number.isRequired
}
static defaultProps = {
isFocused: false
}
constructor(...args) {
super(...args);
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
}
static propTypes = {
name: PropTypes.string.isRequired
}
onFocus() {
setFocus(this.props.index);
}
onBlur() {
clearFocus(this.props.index);
}
render() {
let borderColor = this.props.isFocused ? '#ff0' : '#000';
style = {
border: `1px solid ${borderColor}`
}
return (
<li>
<input
style={style}
type="text"
value={this.props.name}
onFocus={this.onFocus}
onBlur={this.onBlur}
/>
</li>
);
}
}
class App extends Component {
static propTypes = {
people: PropTypes.array.isRequired
}
render() {
let people = this.people.map((person, index) => {
<Person name={person.name} index={index} isFocused={person.isFocused} />
});
return (
<ul>
{people}
</ul>
);
}
}
render();