我有这些增量和递减按钮,将加或减。我将从道具中导入默认值,然后允许用户进行调整。所以当我更新相应组的状态(序列)时,它似乎更新得很好.但是输入值在HTML中仍然是'14‘,尽管我将它设置为value={this.state[mppt_number].series}。当状态发生变化时,它不应该自动更新吗?
这可能与mppt_number变量有关.如果在创建元素时mppt_number =1,那么第二次创建该元素的值不是value={this.state[1].series}和value={this.state[2].series}吗?我不知道。我对这件事有点陌生。
import React from 'react';
//import { defaultValues } from './Calculator';
//Will be passed in as props just have it here for now to ease testing. This can range from 1 to N
const defaultValues = {
1:{
array_isc: 10.88,
array_power: 3834.5999999999995,
array_vmp: 497,
array_voc: 584.3312579999999,
series: 14,
string: 1,
},
2: {array_isc: 9.00,
array_power: 3834.5999999999995,
array_vmp: 600,
array_voc: 584.3312579999999,
series: 12,
string: 1},
}
const mppt = 2
class Tool extends React.Component{
constructor(props){
super(props)
this.state = {
stringSizingElement : null,
}
this.handleStringChange =this.handleStringChange.bind(this)
this.stringSizingElementHelper = this.stringSizingElementHelper.bind(this)
}
componentDidMount() {
let s = {};
for (let i = 1; i <= mppt; i++) {
s[`${i}`] = defaultValues[i];
}
this.setState((prevState) => ({ ...s }), () => {
console.log(this.state);
this.createStringSizingElementDefaults()
});
}
//Create this element mppt_number of times for each MPPT
stringSizingElementHelper( mppt_number){
let stringSizing = (
<div className='container' id ={mppt_number} key = {mppt_number}>
<div className="row justify-content-center">
<label>MPPT {mppt_number}</label>
</div>
<div className="row justify-content-center" id= {`${mppt_number}`}>
<div className="col-4">
<label className='container'>Series</label>
<div className={`input-group container ${`${mppt_number}`}`} >
<button className ='btn btn-primary decrement' onClick={this.handleSeriesChange} >-</button>
<input className="form-control series" min="0" name="quantity" value={this.state[mppt_number].series} type="number" disabled/>
<button className ='btn btn-primary increment' onClick={this.handleSeriesChange} >+</button>
</div>
</div>
</div>
<br/>
<br/>
</div>
);
return stringSizing;
}
createStringSizingElementDefaults(){
let temp = []
//Creating element for each mppt (1:{} , 2: {}) of times for each MPPT This number ranges.
for (let i=1 ; i <= mppt ; i++) {
const result = this.stringSizingElementHelper(i)
temp.push(result)
}
this.setState({stringSizingElement: temp})
}
handleSeriesChange(e){
if(e.target.classList.contains('decrement')){
//Get ID to Figure out which MPPT Is being changed
const mppt_number = e.target.parentNode.parentNode.parentNode.parentNode.id
var newValues = {...this.state[mppt_number]}
newValues.series = this.state[mppt_number].series - 1
this.setState({[mppt_number] : newValues}, ()=>{
console.log(this.state[mppt_number].series)
});
}else if(e.target.classList.contains('increment')){
const mppt_number =
e.target.parentNode.parentNode.parentNode.parentNode.id
var newValues = {...this.state[mppt_number]}
newValues.series = this.state[mppt_number].series + 1
console.log(newValues.series)
this.setState({[mppt_number] : newValues}, ()=>{
console.log(this.state[mppt_number].series)
})
}else{
console.log('Error??')
}
}
render(){
return(
<div className="temp container">
<div className="form-row justify-content-center">
<label htmlFor="sel2"><h4>String Sizing Tool:</h4>
</label>
</div>
{this.state.stringSizingElement}
<br/>
<br/>
{undefined}
<br/>
<br/>
</div>
)
}
}帮助这个女孩?
更新:
不再将这些JSX数组存储在状态中。我现在在渲染和返回之间创建它们。现在,当它存储在一个状态时,它不是在“呈现”?我还是得到了同样的结果。:(
现在,函数返回数组,而不是设置状态。
createStringSizingElementDefaults(){
let temp = []
//Creating element for each mppt (1:{} , 2: {}) of times for each MPPT This number ranges.
for (let i=1 ; i <= mppt ; i++) {
const result = this.stringSizingElementHelper(i)
temp.push(result)
}
return temp
}这个数组现在在呈现和返回之间创建。
render(){
let stringSizingElement = this.createStringSizingElementDefaults()
return(
<div className="temp container">
<div className="form-row justify-content-center">
<label htmlFor="sel2"><h4>String Sizing Tool:</h4></label>
</div>
{stringSizingElement}
<br/>
<br/>
{undefined}
<br/>
<br/>
</div>
)
}帮助后的解决方案代码:
import React from 'react';
//import { defaultValues } from './Calculator';
//import './xxxxx.css';
//Will be passed in as props just have it here for now to ease testing
const defaultValues = {
1: {array_isc: 10.88,
array_power: 3834.5999999999995,
array_vmp: 497,
array_voc: 584.3312579999999,
series: 14,
string: 1,
},
2: {array_isc: 9.00,
array_power: 3834.5999999999995,
array_vmp: 600,
array_voc: 584.3312579999999,
series: 12,
string: 1},
3: {array_isc: 1.00,
array_power: 3834.5999999999995,
array_vmp: 600,
array_voc: 584.3312579999999,
series: 12,
string: 1},
}
class Tool extends React.Component{
constructor(props){
super(props)
this.state = {
}
this.handleStringChange =this.handleStringChange.bind(this)
this.handleSeriesChange =this.handleSeriesChange.bind(this)
}
componentDidMount() {
let s = {};
Object.keys(defaultValues).map((mppt_number, i) => (
s[`${mppt_number}`] = defaultValues[mppt_number]
))
this.setState((prevState) => ({ ...s }), () => {
console.log(this.state);
});
}
handleSeriesChange(e){
if(e.target.classList.contains('decrement')){
//Get ID to Figure out which MPPT Is being changed
console.log(e.target.parentNode.parentNode.parentNode.parentNode.id)
const mppt_number = e.target.parentNode.parentNode.parentNode.parentNode.id
var newValues = {...this.state[mppt_number]}
newValues.series = this.state[mppt_number].series - 1
this.setState({[mppt_number] : newValues}, ()=>{
console.log(this.state[mppt_number].series)
})
}else if(e.target.classList.contains('increment')){
console.log(e.target.parentNode.parentNode.parentNode.parentNode.id)
const mppt_number = e.target.parentNode.parentNode.parentNode.parentNode.id
var newValues = {...this.state[mppt_number]}
newValues.series = this.state[mppt_number].series + 1
this.setState({[mppt_number] : newValues}, ()=>{
console.log(this.state[mppt_number].series)
})
}else{
console.log('Error?? Maybe remove this')
}
}
render(){
return(
<div className="temp container">
<div className="form-row justify-content-center">
<label htmlFor="sel2"><h4>String Sizing Tool:</h4></label>
</div>
{Object.keys(this.state).map((mppt_number, i) => (
<div className='container' id ={mppt_number} key = {mppt_number}>
<div className="row justify-content-center">
<label>MPPT {mppt_number}</label>
</div>
<div className="row justify-content-center" id= {`${mppt_number}`}>
<div className="col-4">
<label className='container'>Series</label>
<div className={`input-group container ${`${mppt_number}`}`} >
<button className ='btn btn-primary decrement' onClick={this.handleSeriesChange} >-</button>
<input className="form-control series" min="0" name="quantity" value={this.state[mppt_number].series} type="number" disabled/>
<button className ='btn btn-primary increment' onClick={this.handleSeriesChange} >+</button>
</div>
</div>
</div>
<br/>
<br/>
</div>
))}
<br/>
<br/>
{undefined}
<br/>
<br/>
</div>
)
}
}发布于 2020-12-19 03:07:52
setStste只覆盖新状态下的旧状态,因此:
this.setState({[mppt_number] : newValues}, ()=>{
console.log(this.state[mppt_number].series)
})不会更新[mppt_number] : newValues,而是将状态替换为{[mppt_number] : newValues}。如果你想:
this.setState((oldState) => ({...oldState, ...{[mppt_number] : newValues}}), ()=>{
console.log(this.state[mppt_number].series)
})以上都会有效的。将对象作为setState的第一个参数并不会导致您想要的更新。赋予一个函数而不是一个对象,就像上面那样。
如果您是新手,而不是立即使用作业,我建议您使用函数组件和钩子,而不是类方法。它很简单,并使代码的前景非常好。试试看!
添加:问题发生在这里:
this.setState({stringSizingElement: temp})temp包含React节点并呈现为初始状态。tringSizingElement在state中总是呈现节点,因此变量被固定为常量值。
为了避免这种情况,停止将节点存储到state中。state中的节点不是反应DOM呈现的作用域,这意味着它们没有更新它们的变量。
createStringSizingElementDefaults(){
let temp = []
for (let i=1 ; i <= mppt ; i++) {
const result = this.stringSizingElementHelper(i)
temp.push(result)
}
return temp
}为了直接生成createStringSizingElementDefaults节点,这个问题不会发生。
加2:
this是一个麻烦的问题。this的观点必须改变你的想法。如果调用this.func.bind(this),则func中的this是固定的。换句话说,this.state从未改变过。因此,即使一次又一次地调用his.createStringSizingElementDefaults(),结果也是一样的!为了避免这两个问题?答案之一是再次调用bind。但在性能方面不推荐。另一个很简单。不能访问成员函数中的状态。如果你愿意的话,把它作为参数。
要做到这一点,“让视图只依赖于状态”可以帮助您。决定只从状态进行视图,并不会引起混淆。这意味着以下例子:
class Example extends React.Component{
constructor(props){
super(props)
this.state = {
somelist: [1, 2, 3],
}
this.handleAppend = this.handleAppend.bind(this)
this.handleRemove = this.handleRemove.bind(this)
}
handleAppend(){
this.setState({someList} => {
let s = [...someList]
s.push(spmeList[someList.length - 1])
return {someList: s}
})
}
handleRemove(){
this.setState({someList} => {
let s = [...someList]
s.pop()
return {someList: s}
})
}
render(){
return(
<div>
<button onClick={this.handleAppend}>Append</button>
<button onClick={this.handleRemove}>Remove</button>
{this.state.someList.map(v => <div>{v}</div>)}
</div>
)
}
}您可以确认该视图仅为状态。要更改状态,需要按下按钮并通过setState事件启动onClick。数据单向流动。这事很重要。
总结一下,
setState获取更新函数this.state (如果愿意的话),将其设为parameters如果您有特殊的情况,我不会停止使用类样式组件,但不会,我强烈建议使用功能性组件样式。
https://stackoverflow.com/questions/65365921
复制相似问题