如何获取 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.statethis.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. 我们不关心用户上次使用该应用时关注的是哪个人,所以我们使用本地状态。
  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();