一个状态属性,只要其值发生变化,就会透明地调用`setState`

时间:2016-06-14 11:28:35

标签: reactjs

我想创建一个状态对象,它结合了状态值本身以及在值改变时调用setState的能力。这样,例如在the container and the dumb component之间的接口上,我不必为每个州的财产传递一个单独的setter。

E.g。通常是在聪明和愚蠢的人中完成的事情。模式如下:

let TextValueContainer = React.createClass({
    getInitialState: function () {
        return {value: ''};
    },
    setValue(v) {
        this.setState({value: v});
    },
    render: function() {
        return (
                <TextValue
                  value={this.state.value}
                  setValue={this.setValue}
                />
        );
    }

});

let TextValue = React.createClass({
    propTypes: {
        value: React.PropTypes.string.isRequired,
        setValue: React.PropTypes.func.isRequired
    },
    render: function() {
        return (
                <input type={'text'}
                    onChange={function (ev) {
                      this.props.setValue(ev.target.value);
                    }.bind(this)}
                    value={this.props.value}
                >
                </input>
        );
    }
});

ReactDOM.render(<TextValueContainer/>, $('#app')[0]);

观察容器和哑组件之间的接口如何传递两个属性:状态值本身(value)和更改它的方法(setValue)。对于N单独的状态属性,我需要在接口处传递2*N props。另外,没有什么难以看出哑组件的代码来确定哪个setter是哪个值。

我进行了一些实验并提出以下建议:

class StateHolder {
    constructor(v, that) {
        this.v = v;
        this.setState = function(v2) {
            this.setState(Object.assign({}
                          ,this.state
                          ,{valueHolder: new StateHolder(v2, that)}));
        }.bind(that);
    }
}


let TextValueContainer = React.createClass({
    getInitialState: function () {
        return {valueHolder: new StateHolder('', this)};
    },
    render: function() {
        return (
                <TextValue
                    valueHolder={this.state.valueHolder}
                />
        );
    }

});

let TextValue = React.createClass({
    propTypes: {
        valueHolder: React.PropTypes.instanceOf(StateHolder).isRequired
    },
    render: function() {
        return (
                <input type={'text'}
                    onChange={function (ev) {
                                this.props.valueHolder.setState(ev.target.value);
                              }.bind(this)}
                    value={this.props.valueHolder.v}
                >
                </input>
        );
    }
});

ReactDOM.render(<TextValueContainer/>, $('#app')[0]);

在上述每个属性的实现中,只需要在“智能”之间传递一个props valueHolder。和愚蠢的&#39;组件(在上面的示例中为sqldf)。

我的问题是:

  1. 有没有更简单的方法来完成我想要做的事情? (即简化“智能”和“哑”组件之间的界面,明确传递的值与其设置函数之间的关联)
  2. 您是否在&#34;解决方案&#34;中看到任何反模式或代码味道?如上所述?

2 个答案:

答案 0 :(得分:1)

告诉我你对这个JSBin有什么看法:http://jsbin.com/tofepoliha/edit?js,output

首先,在声明TextValue元素而不是使用value={this.state.value} value2={this.state.value2}时,我们使用spread(...)运算符在一个操作中传递整个状态。

<TextValue {...this.state} setValue={this.setValue} />

这样我们就不需要为每一处房产重复自己。现在,对于setValue函数 - 我们可以简单地声明一个通用函数,它获取键和值并将其设置为父组件的状态:<{1}}函数 - 而不是为每个属性设置特殊函数。 / p>

setValue(value, v) {
    this.setState({[value]: v});
}

然后,我们可以拥有尽可能多的输入(或其他每个元素):

<input type="text" onChange={function (ev) {
    this.props.setValue('value', ev.target.value);
}.bind(this)} value={this.props.value} />

<input type="text" onChange={function (ev) {
    this.props.setValue('value2', ev.target.value);
}.bind(this)} value={this.props.value2} />

答案 1 :(得分:1)

看起来您想要查看一些框架来管理您的数据流以及应用状态中的相应更改。我最近一直在和Redux合作,我会推荐它。这是Flux架构的一个非常智能的实现。您的“stateHolder”概念在Redux商店中得到解决。

来自Redux动机页面

  

遵循Flux,CQRS和Event Sourcing,Redux的步骤   试图通过强加某些来预测状态突变   更新如何以及何时发生的限制。这些限制   反映在Redux的三个原则中。

当然,还有Redux的替代品;关键是你要做的事情会变得非常难以维持和理解,你应该看一下管理你的状态的一般方法。