- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我终于得到了一个真正有效的响应式设置。但我非常希望得到一些关于这是否是一个良好的设置和数据流的反馈。
我做了以下事情:
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;
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
并不是一个好主意。
我将代码更新为以下内容,但它不起作用..我想我错过了一些事情..
module.exports = {
one: {A: 1,
B: 2,
AB: 2
},
two: { A: 3,
B: 4,
AB: 12
}
};
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;
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;
(不确定我是否在正确的位置使用了 const
和 let
)
在 @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
andthis.Data
(in theupdateDB()
method). References tothis.A
,this.AB
,this.B
andthis.updateDB
in therender()
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;
onChangeA
和 onChangeB
),以处理 A 和 B 的 slider 情况。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/
我是一名优秀的程序员,十分优秀!