Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/extjs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 我应该如何按照单一责任模式处理组件状态_Reactjs_Single Responsibility Principle_React Component - Fatal编程技术网

Reactjs 我应该如何按照单一责任模式处理组件状态

Reactjs 我应该如何按照单一责任模式处理组件状态,reactjs,single-responsibility-principle,react-component,Reactjs,Single Responsibility Principle,React Component,我不熟悉ReactJs,并尝试遵循最佳实践。在我的研究中,我遇到了两篇相互矛盾的文章,讨论如何实现 状态是否应依赖于从父组件传递的属性?在下面的比较中,他们都遵循SRP,但不确定哪一个是最好的。希望得到您的建议,谢谢 1. -- 首先,可能是最重要的一点,组件的状态不应该依赖于传入的道具。(关于我们不应该做的事情,请参见下面的示例) 2. -- 让我们重构一个职责:呈现表单字段和附加事件处理程序。它不应该知道如何直接使用存储……组件从prop initialValue接收存储的输入值,并使用

我不熟悉ReactJs,并尝试遵循最佳实践。在我的研究中,我遇到了两篇相互矛盾的文章,讨论如何实现

状态是否应依赖于从父组件传递的属性?在下面的比较中,他们都遵循SRP,但不确定哪一个是最好的。希望得到您的建议,谢谢

1. -- 首先,可能是最重要的一点,组件的状态不应该依赖于传入的道具。(关于我们不应该做的事情,请参见下面的示例)

2. -- 让我们重构一个职责:呈现表单字段和附加事件处理程序。它不应该知道如何直接使用存储……组件从prop initialValue接收存储的输入值,并使用prop函数saveValue(newValue)保存输入值。这些道具是由withPersistence()HOC使用道具代理技术提供的

3. -- 在我的例子中,我有如下内容(想知道这是否是一个可接受的实现?)-状态应该在任务中处理,还是在位于TasksWithData和Tasks之间的另一种TasksWithPersistence类型的组件中处理?
导出默认函数TasksWithData(TasksComponent){
返回数据扩展为React.Component的类{
render(){
const tasks=TaskAPI.getTasks();
返回(
)
}
}
}
导出默认类任务扩展React.Component{
状态={
任务:[],
addItemInput:null
};
// ...
componentDidMount(){
this.updateComponentState({tasks:this.props.tasks});
}
componentDidUpdate(){
此.prepuifornextadition();
}
// ...
}

示例1和示例2之间存在巨大差异

在示例#1中,以这种方式设置这些道具的状态不好的原因是,如果道具更改,小部件将不会更新。无论是否是最佳实践,这在任何框架中都是错误和糟糕的。在这种特殊情况下,甚至使用状态都没有意义。单靠道具就足够了

在示例#2中,道具仅用于为状态提供初始值(道具甚至被命名为
initialValue
),这意味着无论道具如何变化,状态的进一步变化都将由组件控制。在初始状态中使用道具并不违反单一责任原则,特别是当它明确用于该目的时


我真的不认为这两个例子是矛盾的,因为它们完全不同。此外,在单一责任原则中没有规则规定不能从道具中设置状态,你只需要注意你所处的环境。

你的问题的要点似乎围绕着这样一个问题,即使用一些道具并将其复制到状态中。这是道具的变异,不是国家的目的。道具是一成不变的,将它们复制到国家会挫败这种设计

状态的目的是管理特定于React组件的内容,即仅严格限定于该React组件。例如,要在React组件中显示的内容的showHide开关。如果有帮助,可以将状态视为一个局部作用域变量

大多数情况下,这种复制道具的反模式可以通过React对象中的函数来满足。例如,state.full_name变量成为绑定到React组件的命名函数fullName。(所有代码示例均采用JSX语法)

注意:在JavaScript中,函数和变量的命名结构,我假设您来自ruby,基于下划线命名约定。在我看来,最好遵守编写代码所用语言的惯例。这就是我使用camelcased命名的原因

然后可以在组件的渲染中调用该函数

# in render() portion of your React component, assuming jsx syntax
<p>Hello, {this.fullName()}</p>
您还可以将相关部分分解为名为FullName的新组件(如果多个组件将使用该组件)

<FullName firstName={this.props.firstName} lastName={this.props.lastName} />

从技术上讲,“反应方式”是,至少在作者看来,将其分解为另一个组件以实现可重用性。然而,组件重用需要根据增加的复杂性进行权衡,即不要过早优化。所以一开始你可能不想走得太远。必要的时候自然会出现

React道具的一个非常广泛的概括是,它们是有保证的,是不变的,并且它们像瀑布一样从最顶端的组件向下流动。如果需要更新它们,请在有意义的最高级别进行更新

在基于soley React的方法中,如果您有某个父级需要知道的内容,请将该部分代码“提升”到父级,反之亦然,将其作为道具绑定到子级,例如调用API的AJAX函数。我认为这是为了尽可能地让组件保持沉默

父母成为你“举起”的物品的“真相之源”。父级处理更新,然后将结果传递给子级。因此,在父对象中,它可能作为状态变量存在,然后作为道具传递给子对象,然后子对象将其作为道具传递给它的子对象,等等。当状态作为道具在链中向下传播时,子对象将随着其父对象中状态的更改而更新

如果您的应用程序仅为React,即没有管理对象的存储,如flux模式或redux模式,则您可能必须将内容存储在最顶层的objet状态,从技术上讲,这可能被视为不好的。随着系统变得越来越复杂,flux或redux的部件将更好地处理此功能

希望这有帮助

这个答案有用吗?作为一名学习者,我避免在构造函数中设置状态。一般来说,我直接使用它们而不使用gett
export default function TasksWithData(TasksComponent) {  

    return class withData extends React.Component {
        render() {
            const tasks = TaskAPI.getTasks();
            return (
                <TasksComponent 
                    tasks={tasks} 
                    {...this.props} 
                />
            )
        }
    }

}


export default class Tasks extends React.Component {

    state = { 
        tasks: [], 
        addItemInput: null 
    };

    // ...

    componentDidMount() {
        this.updateComponentState({tasks: this.props.tasks});
    }

    componentDidUpdate() {
        this.prepUIForNextAddition();
    }

    // ...
}
...
fullName() {
    return this.props.firstName + " " + this.props.lastName
} 
...
# in render() portion of your React component, assuming jsx syntax
<p>Hello, {this.fullName()}</p>
...
constructor(props) {
  super(props);
  this.fullName = this.fullName.bind(this);
}
...
<FullName firstName={this.props.firstName} lastName={this.props.lastName} />