Javascript 反应:这是使用道具和状态的好方法吗
我终于得到了一个实际有效的响应设置。但我非常想得到一些反馈,看看这是否是一个好的设置和数据流 我作了以下发言: App.js App.js scr/dummy-data.js scr/components/ABEval.jsJavascript 反应:这是使用道具和状态的好方法吗,javascript,reactjs,Javascript,Reactjs,我终于得到了一个实际有效的响应设置。但我非常想得到一些反馈,看看这是否是一个好的设置和数据流 我作了以下发言: App.js App.js scr/dummy-data.js scr/components/ABEval.js import React,{Component}来自'React'; 从“/XSlider”导入XSlider; 类AB_eval扩展了组件{ 构造函数(道具、上下文){ 超级(道具、背景); log(`${this.props.ID}:Constructed`); } c
import React,{Component}来自'React';
从“/XSlider”导入XSlider;
类AB_eval扩展了组件{
构造函数(道具、上下文){
超级(道具、背景);
log(`${this.props.ID}:Constructed`);
}
componentDidMount(){
log(`${this.props.ID}:Mounted`);
}
render(){
log(`${this.props.ID}:rendered`)
const{Data,ID}=this.props;
常数{A,B,AB}=数据;
返回(
ABEval:{ID}
A:{A}B:{B}AB:{AB}
this.props.updateDB(ID,{A:val,B:B,AB:val*B})
/>
this.props.updateDB(ID,{B:val,A:A,AB:val*A})
/>
)
}
}
AB_eval.propTypes={
ID:React.PropTypes.string.isRequired,
数据:React.PropTypes.object.isRequired,
更新的b:React.PropTypes.func.isRequired
};
导出默认值;
scr/components/XSlider.js
从“React”导入React;
从“react Range Slider”导入滑块;
导出默认值({title,value,valueHandler})=>{
返回(
{title}
);
}
在您的示例中,无需在App
组件中执行updateDB
。您只需在AB_eval
中执行updateDB
操作即可。您可以在AB_eval
构造函数中初始化A
,B
,而不是从App
组件获取,因为它们是常量。在您的示例中,不必在App
组件中执行updateDB
。您只需在AB_eval
中执行updateDB
操作即可。您可以在AB_eval
构造函数中初始化A
,B
,而不是从App
组件中获取,因为它们是常量。根据您提供的信息,很难提出许多重新分解的建议,但数据流看起来不错
最新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
是块范围的,因此在
构造函数将仅在
构造块
这将中断以后对This.ID
和This.Data
的引用(在
updateDB()
method)。对this.A
、this.AB
、this.B
和
render()
方法中的this.updateDB
也将被破坏。修理
这一点,我建议在你的区块范围内分解道具
呈现和onChange处理程序
正在尝试直接在中设置this.props.Data的值
onChange方法有效地改变了应该被视为
不变的
有几种方法可以确保使用ES6/ES7不会发生突变
表示法,一个使用,另一个使用
解决方案
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;
因此,您还必须编辑我建议的AB_eval.js以包括:从“/components/AB_eval_Slider”导入AB_eval_滑块代码>
现在的渲染方法是:
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>
);
}
render(){
返回(
const{Data}=this.props;
AB_eval:{this.ID}
);
}
根据您提供的信息,很难提出许多重新分解的建议,但数据流看起来还行
最新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
是块范围的,因此在
构造函数将仅在
构造块
这将中断以后对This.ID
和This.Data
的引用(在
updateDB()
method)。对this.A
、this.AB
、this.B
和
render()
方法中的this.updateDB
也将被破坏。修理
这一点,我建议在你的区块范围内分解道具
呈现和onChange处理程序
正在尝试直接在中设置this.props.Data的值
onChange方法有效地改变了应该被视为
不变的
有几种方法可以确保使用ES6/ES7不会发生突变
表示法,一个使用,另一个使用
解决方案
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;
因此,您还必须编辑我建议的AB_eval.js以包括:
从“/components/AB_eval_Slider”导入AB_eval_滑块代码>
现在的渲染方法是:
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>
);
}
render(){
返回(
const{Data}=this.props;
AB_eval:{this.ID}
);
}
老实说,我不明白你的代码是干什么用的,但从代码示例和你的问题来看,我不明白
我能想到的是:
dummyData.js
export default {
one: {A: 1,
B: 2,
AB: 2
},
two: { A: 3,
B: 4,
AB: 12
}
};
import React, { Component } from 'react';
import './App.css';
import dummyData from './dummyData';
import AB_eval from './components/AB_eval';
class App extends Component {
constructor() {
super();
// getInitialState
this.state = dummyData;
this.updateDB = (id, value) => this.setState({ id: value });
}
render() {
return (
<div className="App">
<ul className="list-of-ABs">
{ Object
.keys(this.state)
.map(key =>
<AB_eval
key = {key}
ID = {key}
Data = {this.state[key]}
updateDB={this.updateDB} />
)
}
</ul>
</div>
);
}
}
export default App;
import React, { Component } from 'react';
import Slider from 'react-rangeslider';
class AB_eval extends Component {
constructor(props, context){
super(props, context);
this.updateDB = (type, value) => {
const { ID, DATA } = this.props
switch(type) {
case "A":
this.props.updateDB(
ID,
{ ...DATA, A: value, AB: (value * DATA.B) }
);
break;
case "B":
this.props.updateDB(
ID,
{ ...DATA, B: value, AB: (DATA.A * value) }
);
break;
default:
this.props.updateDB(
ID, DATA
);
break;
}
};
}
componentDidMount () {
this.updateDB();
}
render() {
const {A, B, AB} = this.props.DATA;
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.updateDB("A", value) }
}
/>
<h2>B</h2>
<p>A: {A} B: {B} AB:{AB}</p>
<Slider min={1} max={4} step={1}
value={B}
onChange={ (value)=> this.updateDB("B", value) }
/>
</div>
)
}
}
AB_eval.propTypes = {
ID: React.PropTypes.string.isRequired,
DATA: React.PropTypes.object.isRequired,
updateDB: React.PropTypes.func.isRequired
};
export default AB_eval;
App.js
export default {
one: {A: 1,
B: 2,
AB: 2
},
two: { A: 3,
B: 4,
AB: 12
}
};
import React, { Component } from 'react';
import './App.css';
import dummyData from './dummyData';
import AB_eval from './components/AB_eval';
class App extends Component {
constructor() {
super();
// getInitialState
this.state = dummyData;
this.updateDB = (id, value) => this.setState({ id: value });
}
render() {
return (
<div className="App">
<ul className="list-of-ABs">
{ Object
.keys(this.state)
.map(key =>
<AB_eval
key = {key}
ID = {key}
Data = {this.state[key]}
updateDB={this.updateDB} />
)
}
</ul>
</div>
);
}
}
export default App;
import React, { Component } from 'react';
import Slider from 'react-rangeslider';
class AB_eval extends Component {
constructor(props, context){
super(props, context);
this.updateDB = (type, value) => {
const { ID, DATA } = this.props
switch(type) {
case "A":
this.props.updateDB(
ID,
{ ...DATA, A: value, AB: (value * DATA.B) }
);
break;
case "B":
this.props.updateDB(
ID,
{ ...DATA, B: value, AB: (DATA.A * value) }
);
break;
default:
this.props.updateDB(
ID, DATA
);
break;
}
};
}
componentDidMount () {
this.updateDB();
}
render() {
const {A, B, AB} = this.props.DATA;
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.updateDB("A", value) }
}
/>
<h2>B</h2>
<p>A: {A} B: {B} AB:{AB}</p>
<Slider min={1} max={4} step={1}
value={B}
onChange={ (value)=> this.updateDB("B", value) }
/>
</div>
)
}
}
AB_eval.propTypes = {
ID: React.PropTypes.string.isRequired,
DATA: React.PropTypes.object.isRequired,
updateDB: React.PropTypes.func.isRequired
};
export default AB_eval;
我首先想到的是您的AB_eval
组件,它不需要自己的状态。因为它的所有状态的内容都可以通过道具
获得。正如React
上所述,您应该:
计算出应用程序所需状态的绝对最小表示形式,并按需计算所需的所有其他内容
将状态放在一个位置,通常放在组件层次结构顶部的组件中,这会使您更容易理解应用程序
我认为当您想在React
中创建应用程序时,在React的
文档站点上的这一点可以帮助您很多
这是一个关于const
和let
的好教程。但简而言之,,
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>
);
}
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>
);
}
export default {
one: {A: 1,
B: 2,
AB: 2
},
two: { A: 3,
B: 4,
AB: 12
}
};
import React, { Component } from 'react';
import './App.css';
import dummyData from './dummyData';
import AB_eval from './components/AB_eval';
class App extends Component {
constructor() {
super();
// getInitialState
this.state = dummyData;
this.updateDB = (id, value) => this.setState({ id: value });
}
render() {
return (
<div className="App">
<ul className="list-of-ABs">
{ Object
.keys(this.state)
.map(key =>
<AB_eval
key = {key}
ID = {key}
Data = {this.state[key]}
updateDB={this.updateDB} />
)
}
</ul>
</div>
);
}
}
export default App;
import React, { Component } from 'react';
import Slider from 'react-rangeslider';
class AB_eval extends Component {
constructor(props, context){
super(props, context);
this.updateDB = (type, value) => {
const { ID, DATA } = this.props
switch(type) {
case "A":
this.props.updateDB(
ID,
{ ...DATA, A: value, AB: (value * DATA.B) }
);
break;
case "B":
this.props.updateDB(
ID,
{ ...DATA, B: value, AB: (DATA.A * value) }
);
break;
default:
this.props.updateDB(
ID, DATA
);
break;
}
};
}
componentDidMount () {
this.updateDB();
}
render() {
const {A, B, AB} = this.props.DATA;
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.updateDB("A", value) }
}
/>
<h2>B</h2>
<p>A: {A} B: {B} AB:{AB}</p>
<Slider min={1} max={4} step={1}
value={B}
onChange={ (value)=> this.updateDB("B", value) }
/>
</div>
)
}
}
AB_eval.propTypes = {
ID: React.PropTypes.string.isRequired,
DATA: React.PropTypes.object.isRequired,
updateDB: React.PropTypes.func.isRequired
};
export default AB_eval;