gpt4 book ai didi

javascript - react : Is this a good way to use props and states

转载 作者:行者123 更新时间:2023-12-02 14:01:58 25 4
gpt4 key购买 nike

我终于得到了一个真正有效的响应式设置。但我非常希望得到一些关于这是否是一个良好的设置和数据流的反馈。

我做了以下事情:

App.js

import React, { Component } from 'react';
import './App.css';
import AB_eval from './components/AB_eval';

class App extends Component {
constructor() {
super();
this.updateDB = this.updateDB.bind(this);
// getInitialState
this.state = {
DB: []
};
}

updateDB(k, bar) {
const DB = {...this.state.DB}
DB[k] = bar;
this.setState({ DB });
}

render() {
return (
<div className="App">

<AB_eval A={2} B={3} updateDB={this.updateDB} />

</div>
);
}
}

export default App;

AB_eval.js

import React, { Component } from 'react';
import Slider from 'react-rangeslider';

class AB_eval extends Component {
constructor(props, context){
super(props, context);

this.updateDB = this.updateDB.bind(this);
this.refreshAB = this.refreshAB.bind(this);

let {A, B} = this.props;
let AB = A * B;
this.state = {
A: A,
B: B,
AB: AB
}
}

componentDidMount () {
this.updateDB();
}

refreshAB () {
const AB = this.state.A * this.state.B;
this.setState({
AB: AB
});
}

updateDB () {
const bar = {
A: this.state.A,
B: this.state.B,
AB: this.state.AB
}
this.props.updateDB(0, bar) // updating the App's state
}

render() {
let {A, B, AB} = this.state;
return (
<div>
<h1>AB_eval: {AB}</h1>


<h2>A</h2>
<p>A: {A} B: {B} AB:{AB}</p>
<Slider min={1} max={4} step={1}
value={A}
onChange={ (value)=> {
this.setState({
A: value
});
this.refreshAB()
this.updateDB() }
}
/>

<h2>B</h2>
<p>A: {A} B: {B} AB:{AB}</p>
<Slider min={1} max={4} step={1}
value={B}
onChange={ (value)=> {
this.setState({
B: value
});
this.refreshAB()
this.updateDB() }
}
/>
</div>
)
}
}

AB_eval.propTypes = {
A: React.PropTypes.number.isRequired,
B: React.PropTypes.number.isRequired,
updateDB: React.PropTypes.func.isRequired
};

export default AB_eval;

下一步是添加一个 C slider - 所以它将成为一个 ABC_eval。但首先我需要知道:

  • 应用程序和 AB_eval 之间的数据流是一个好方法吗?

  • 将事物分解为更多组件有意义吗?

<小时/>

更新

我意识到,在循环状态时,在 AB_eval 组件内使用 setState 并不是一个好主意。

我将代码更新为以下内容,但它不起作用..我想我错过了一些事情..

虚拟数据.js

module.exports = {
one: {A: 1,
B: 2,
AB: 2
},
two: { A: 3,
B: 4,
AB: 12
}
};

App.js

import React, { Component } from 'react';
import './App.css';
import AB_eval from './components/AB_eval';
import dummyData from './dummy-data';

class App extends Component {
constructor() {
super();
this.updateDB = this.updateDB.bind(this);

// getInitialState
this.state = {
DB: dummyData
};
}

updateDB(key, bar) {
const DB = {...this.state.DB}
DB[key] = bar;
this.setState({ DB });
}

render() {
return (
<div className="App">
<ul className="list-of-ABs">
{ Object
.keys(this.state.DB)
.map(key =>
<AB_eval
key = {key}
ID = {key}
Data = {this.state.DB[key]}
updateDB={this.updateDB} />
)
}
</ul>
</div>
);
}
}

export default App;

AB_eval.js

import React, { Component } from 'react';
import Slider from 'react-rangeslider';

class AB_eval extends Component {
constructor(props, context){
super(props, context);

this.updateDB = this.updateDB.bind(this);

// Trying to make these variable instance variables
const {ID, Data} = this.props;

}

updateDB () {
this.props.updateDB(this.ID, this.Data) // updating the App's state
}

render() {
console.log(this.Data);
let {A, B, AB} = this.Data;
return (
<div>
<h1>AB_eval: {this.ID}</h1>

<h2>A</h2>
<p>A: {A} B: {B} AB:{AB}</p>
<Slider min={1} max={4} step={1}
value={A}
onChange={ (value)=> {
this.A = value;
this.AB = this.A * this.B;
this.updateDB();
}
}
/>

<h2>B</h2>
<p>A: {A} B: {B} AB:{AB}</p>
<Slider min={1} max={4} step={1}
value={B}
onChange={ (value)=> {
this.B = value;
this.AB = this.A * this.B;
this.updateDB();
}
}
/>
</div>
)
}
}

AB_eval.propTypes = {
ID: React.PropTypes.string.isRequired,
Data: React.PropTypes.object.isRequired,
updateDB: React.PropTypes.func.isRequired
};

export default AB_eval;

(不确定我是否在正确的位置使用了 constlet)

<小时/>

解决方案

在 @Pineda 的帮助和一些尝试下,我发现以下解决方案可以按我的意愿工作:

scr/App.js

import React, { Component } from 'react';
import './App.css';
import ABEval from './components/ABEval';
import dummyData from './dummy-data';

class App extends Component {
constructor() {
super();
this.updateDB = this.updateDB.bind(this);

// getInitialState
this.state = {
DB: dummyData
};
}

updateDB(key, bar) {
const DB = {...this.state.DB}
DB[key] = bar;
this.setState({ DB });
}

render() {
return (
<div className="App">
<ul className="list-of-ABs">
{ Object
.keys(this.state.DB)
.map(key =>
<ABEval
key={key}
ID={key}
Data={this.state.DB[key]}
updateDB={this.updateDB} />
)
}
</ul>
</div>
);
}
}

export default App;

scr/dummy-data.js

module.exports = {
one: {A: 1,
B: 2,
AB: 2
},
two: { A: 3,
B: 4,
AB: 12
}
};

scr/components/ABEval.js

import React, { Component } from 'react';
import XSlider from './XSlider';

class AB_eval extends Component {
constructor(props, context){
super(props, context);
console.log(`${this.props.ID}: Constructed`);
}

componentDidMount(){
console.log(`${this.props.ID}: Mounted`);
}

render() {
console.log(`${this.props.ID}: rendered`)
const { Data, ID } = this.props;
const { A, B, AB } = Data;
return (
<div>
<h1>ABEval: {ID}</h1>
<p>A: {A} B: {B} AB:{AB}</p>

<XSlider
title={'A'}
value={A}
valueHandler={
(val)=> this.props.updateDB(ID, {A: val, B: B, AB: val*B} )}
/>

<XSlider
title={'B'}
value={B}
valueHandler={
(val)=> this.props.updateDB(ID, {B: val, A: A, AB: val*A} )}
/>
</div>
)
}
}

AB_eval.propTypes = {
ID: React.PropTypes.string.isRequired,
Data: React.PropTypes.object.isRequired,
updateDB: React.PropTypes.func.isRequired
};

export default AB_eval;

scr/components/XSlider.js

import React from 'react';
import Slider from 'react-rangeslider';

export default ({title, value, valueHandler}) => {
return (
<div>
<h2>{title}</h2>
<Slider min={1} max={4} step={1} value={value} onChange={valueHandler} />
</div>
);
}

最佳答案

根据您提供的信息,很难提出许多重构建议,但数据流看起来不错。

最新 AB_eval.js 中的问题:

const {ID, Data} = this.props;  // block scoped, DOES NOT create class members
// referencable by this.ID or this.DATA
// outside the scope of its containing block

const is block scoped so your destructuring of props within the constructor will only create a useable value of ID and Data within the constructor block.

This breaks later references of this.ID and this.Data (in the updateDB() method). References to this.A, this.AB, this.B and this.updateDB in the render() method will also be broken. To fix this, I suggest destructuring the props within the block scope of your render and onChange handler(s).

this.AB = this.A * this.B;  // state should be treated as immutable
// and since props are propogated by changes in state
// mutating them is ill-advised

Attempting to set values on this.props.Data directly within the onChange methods which is effectively mutating what should be treated as immutable.

There are a couple ways you can ensure no mutations using ES6/ES7 notation, one is using Object.assign and the other is using the Spread syntax notation.

解决方案

AB_eval.js:

import React, { Component } from 'react';
import Slider from 'react-rangeslider';

class AB_eval extends Component {
constructor(props, context){
super(props, context);

this.onChangeA = this.onChangeA.bind(this);
this.onChangeB = this.onChangeB.bind(this);
}

onChangeA (value) {
const {ID, Data, updateDB} = this.props;
updateDB(ID, {
...Data,
A: value,
AB: value * Data.B
});
}

onChangeB (value) {
const {ID, Data, updateDB} = this.props;
updateDB(ID, {
...Data,
B: value,
AB: value * Data.B
});
}

render() {
const {A, B, AB} = this.props.Data;
return (
<div>
<h1>AB_eval: {this.props.ID}</h1>

<h2>A</h2>
<p>A: {A} B: {B} AB:{AB}</p>
<Slider min={1} max={4} step={1}
value={A}
onChange={this.onChangeA}
/>

<h2>B</h2>
<p>A: {A} B: {B} AB:{AB}</p>
<Slider min={1} max={4} step={1}
value={B}
onChange={this.onChangeB}
}
/>
</div>
)
}
}

AB_eval.propTypes = {
ID: React.PropTypes.string.isRequired,
Data: React.PropTypes.object.isRequired,
updateDB: React.PropTypes.func.isRequired
};

export default AB_eval;
  • 单个 updateDB 方法已替换为两个 onChange 处理程序(分别为 onChangeAonChangeB),以处理 A 和 B 的 slider 情况。
  • Prop 在这些处理程序以及渲染函数中进行了相应的解构,请注意扩展语法的使用,以便创建不会改变现有 this.Data.props 的更新对象
  • onChange 处理程序不再使用之前的粗箭头表示法,因此有必要将两个处理程序绑定(bind)到 this
<小时/>

关于重构的更新:
您可以将 slider 代码提取到功能组件中(我添加了一个文件夹结构作为建议):

./components/AB_eval_slider.js

import React from 'react';

export default ({key, db, handler}) => {
return (
<div>
<h2>{key}</h2>
<p>A: {db.A} B: {db.B} AB:{db.AB}</p>
<Slider min={1} max={4} step={1} value={key} onChange={handler} />
</div>
);
}

因此,您还必须编辑我建议的 AB_eval.js 以包含:
从'./components/AB_eval_slider'导入AB_eval_Slider;

渲染方法现在是:

render() {
return (
const { Data } = this.props;
<div>
<h1>AB_eval: {this.ID}</h1>
<AB_eval_Slider key={'A'} db={Data}, handler={this.onChangeA} />
<AB_eval_Slider key={'B'} db={Data}, handler={this.onChangeB} />
</div>
);
}

关于javascript - react : Is this a good way to use props and states,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40332557/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com