首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >输入值在setState更改后不更新.增减

输入值在setState更改后不更新.增减
EN

Stack Overflow用户
提问于 2020-12-19 01:45:09
回答 1查看 609关注 0票数 0

我有这些增量和递减按钮,将加或减。我将从道具中导入默认值,然后允许用户进行调整。所以当我更新相应组的状态(序列)时,它似乎更新得很好.但是输入值在HTML中仍然是'14‘,尽管我将它设置为value={this.state[mppt_number].series}。当状态发生变化时,它不应该自动更新吗?

这可能与mppt_number变量有关.如果在创建元素时mppt_number =1,那么第二次创建该元素的值不是value={this.state[1].series}value={this.state[2].series}吗?我不知道。我对这件事有点陌生。

代码语言:javascript
复制
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数组存储在状态中。我现在在渲染和返回之间创建它们。现在,当它存储在一个状态时,它不是在“呈现”?我还是得到了同样的结果。:(

现在,函数返回数组,而不是设置状态。

代码语言:javascript
复制
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

    }

这个数组现在在呈现和返回之间创建。

代码语言:javascript
复制
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>
    )
}

帮助后的解决方案代码:

代码语言:javascript
复制
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>
        )
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-19 03:07:52

setStste只覆盖新状态下的旧状态,因此:

代码语言:javascript
复制
            this.setState({[mppt_number] : newValues}, ()=>{
                console.log(this.state[mppt_number].series)
            })

不会更新[mppt_number] : newValues,而是将状态替换为{[mppt_number] : newValues}。如果你想:

代码语言:javascript
复制
            this.setState((oldState) => ({...oldState, ...{[mppt_number] : newValues}}), ()=>{
                console.log(this.state[mppt_number].series)
            })

以上都会有效的。将对象作为setState的第一个参数并不会导致您想要的更新。赋予一个函数而不是一个对象,就像上面那样。

如果您是新手,而不是立即使用作业,我建议您使用函数组件和钩子,而不是类方法。它很简单,并使代码的前景非常好。试试看!

添加:问题发生在这里:

代码语言:javascript
复制
        this.setState({stringSizingElement: temp})

temp包含React节点并呈现为初始状态。tringSizingElementstate中总是呈现节点,因此变量被固定为常量值。

为了避免这种情况,停止将节点存储到state中。state中的节点不是反应DOM呈现的作用域,这意味着它们没有更新它们的变量。

代码语言:javascript
复制
    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。但在性能方面不推荐。另一个很简单。不能访问成员函数中的状态。如果你愿意的话,把它作为参数。

要做到这一点,“让视图只依赖于状态”可以帮助您。决定只从状态进行视图,并不会引起混淆。这意味着以下例子:

代码语言:javascript
复制
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

  • 保持数据流单向

如果您有特殊的情况,我不会停止使用类样式组件,但不会,我强烈建议使用功能性组件样式。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65365921

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档