1

The following subcomponent successfully updates the default values of each individual render properly and display text values on update.

BUT...

when I navigate to another record I am unable to see the updated textbox value changed, it holds on to the previous record's value (even the updated state of that record)?

How do I completely re-fetch new values?

import React from 'react';
import './EditRisk.css';

export class EditRiskDetails extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            riskTitle: props.risk.risktitle,
            riskStatement: props.risk.riskstatement,
            riskContext: props.risk.riskcontext,
            clousreCriteria: props.risk.closurecriteria,
            onwerNotes: props.risk.ownernotes,
            approverComments: props.risk.approvercomments
        }
    }
    handleRiskTitleChange = (event) => {    
        this.setState({riskTitle: event.target.value});
        this.props.risk.risktitle = event.target.value; 
    }
    handleRiskStatementChange = (event) => {   
        this.setState({riskStatement: event.target.value}); 
        this.props.risk.riskstatement = event.target.value; 
    }
    handleRiskContextChange = (event) => {    
        this.setState({riskContext: event.target.value});
        this.props.risk.riskcontext = event.target.value;
    }
    handleClosureCriteriaChange = (event) => {    
        this.setState({closureCriteria: event.target.value}); 
        this.props.risk.closurecriteria = event.target.value;  
    }
    handleOwnerNotesChange = (event) => {    
        this.setState({ownerNotes: event.target.value});  
        this.props.risk.ownernotes = event.target.value; 

    }
    handleApproverCommentsChange = (event) => {    
        this.setState({approverComments: event.target.value});  
        this.props.data.approvercomments = event.target.value;
    }
    componentDidUpdate(e){
        
    }
    render() {
        return (
            <div id="details" class="tbl layout" border="1">
                <div class="tr text input">
                    <div class="td label" style={{verticalAlign: 'top'}}>
                        Title
                    </div>
                    <div class="td input data text">
                        <input type="text" onKeyPress={this.handleRiskTitleChange} defaultValue={this.state.riskTitle}/>
                    </div>
                </div>
                <div class="tr">
                    <div class="td label" style={{verticalAlign: 'top'}}>
                        Risk Statement
                    </div>
                    <div class="td data"  style={{verticalAlign: 'top'}}>
                        <textarea onKeyPress={this.handleRiskStatementChange} defaultValue={this.state.riskStatement}></textarea>
                    </div>
                </div>
                <div class="tr">
                    <div class="td label"  style={{verticalAlign: 'top'}}>
                        Context
                    </div>
                    <div class="td data"  style={{verticalAlign: 'top'}}>
                        <textarea onKeyPress={this.handleRiskContextChange} defaultValue={this.state.riskContext}></textarea>
                    </div>
                </div>
                <div class="tr">
                    <div class="td label"  style={{verticalAlign: 'top'}}>
                        Closure Criteria
                    </div>
                    <div class="td data"  style={{verticalAlign: 'top'}}>
                        <textarea onKeyPress={this.handleClosureCriteriaChange} defaultValue={this.state.closureCriteria}></textarea>
                    </div>
                </div>
                <div class="tr">
                    <div class="td label"  style={{verticalAlign: 'top'}}>
                        Owner Notes
                    </div>
                    <div class="td data"  style={{verticalAlign: 'top'}}>
                        <textarea onKeyPress={this.handleOwnerNotesChange} defaultValue={this.state.ownerNotes}></textarea>
                    </div>
                </div>
                <div class="tr">
                    <div class="td label" style={{verticalAlign: 'top'}}>
                        Approver Comments
                    </div>
                    <div class="td data"  style={{verticalAlign: 'top'}}>
                        <textarea onKeyPress={this.handleApproverCommentsChange} defaultValue={this.state.approverComments}></textarea>
                    </div>
                </div>
            </div>
        );
    }
}

An adjacent subcomponent updates just fine:

import React from 'react';
import Select from 'react-select';
import { riskValue } from '../../common/Functions';
import './EditRisk.css';

export class EditRiskSummary extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            selectedOwnerId: this.props.data.risk.ownerid,
            selectedApproverId: this.props.data.risk.approverid
        }
    }
    handleOwnerChange = (option) => {
        this.setState({selectedOwnerId: option.value});
        this.props.data.risk.ownerid = option.value;
    }
    handleApproverChange = (option) => {
        this.setState({selectedApproverId: option.value});
        this.props.data.risk.approverid = option.value;
    }
    componentDidUpdate(e) {
        let ownerChanged = this.state.selectedOwnerId !== e.data.risk.ownerid;
        let approverChanged = this.state.selectedApproverId !== e.data.risk.approverid;
        this.state = {
            selectedOwnerId: e.data.risk.ownerid,
            selectedApproverId: e.data.risk.approverid
        }
        return ownerChanged || approverChanged;
    }
    
    render() {
        return (
            <div className="tbl layout" id="summary">
                <div className="tr">
                    <div className="td label">Risk #</div>
                    <div className="td">{this.props.data.risk.riskid} [<a href="" onClick="ctrl.getRiskReport()">Risk Summary</a>]</div>
                    <div className="td label">
                        Current Risk
                    </div>
                    <div className="td {this.props.risk.currentlevel}">
                        {riskValue(this.props.data.risk.currentlevel, this.props.data.risk.currentlikelihood, this.props.data.risk.currentconsequence)}
                    </div>
                </div>   
                <div className="tr">
                    <div className="td label">        
                        Creator
                    </div>
                    <div className="td">
                        Admin
                    </div>
                    <div className="td label">
                        Risk State
                    </div>
                    <div className="td">
                        {this.props.data.risk.riskstate}
                    </div>
                </div>      
                <div className="tr">
                    <div className="td label">
                        Owner
                    </div>
                    <div className="td">
                        <Select value={this.props.data.users.filter(option => option.value === this.props.data.risk.ownerid)} 
                                options={this.props.data.users} 
                                onChange={this.handleOwnerChange.bind(this)} />
                    </div>
                    <div className="td label">
                        Risk Approver
                    </div>
                    <div className="td">
                        <Select value={this.props.data.users.filter(option => option.value === this.props.data.risk.approverid)} 
                                options={this.props.data.users} 
                                onChange={this.handleApproverChange.bind(this)} />
                    </div>
                </div>
            </div>
        );
    }
}
Vahe
  • 1,699
  • 3
  • 25
  • 76
  • Note: Navigation subcomponent controls the paged fetch of records, as I am using passed down props to manage data – Vahe May 30 '22 at 20:59
  • Update: On Browser Inspect This comes up: react-dom.development.js:86 Warning: Expected EditRiskSummary state to match memoized state before processing the update queue. This might either be because of a bug in React, or because a component reassigns its own `this.state`. Please file an issue. – Vahe May 30 '22 at 21:07
  • Updated Note: value= works but is only readonly, defaultValue allows updating value on entry but does not work on fetch... How do I fix this? – Vahe May 30 '22 at 21:57

1 Answers1

1

EditDetailRisks component has the following bugs.

  • this.props.risk.risktitle = event.target.value; In React component, updating props or state directly isn't recommended. You should update props or state using setState.
  • The cause that doesn't update the changed values is that you passed the states as defaultValue, not value in textarea. defaultValue property is used to set the initial value only when loading the DOM element.

I updated EditRiskDetails component code and look forward that it will help your understanding.

import React from 'react';
import './EditRisk.css';

export class EditRiskDetails extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            riskTitle: props.risk.risktitle,
            riskStatement: props.risk.riskstatement,
            riskContext: props.risk.riskcontext,
            clousreCriteria: props.risk.closurecriteria,
            onwerNotes: props.risk.ownernotes,
            approverComments: props.risk.approvercomments
        }
    }
    
    handleInputChange = (event, key) => {    
        this.setState({[key]: event.target.value});
    }

    componentDidUpdate(e){
        
    }
    
    render() {
        return (
            <div id="details" class="tbl layout" border="1">
                <div class="tr text input">
                    <div class="td label" style={{verticalAlign: 'top'}}>
                        Title
                    </div>
                    <div class="td input data text">
                        <input type="text" onKeyPress={(event) => this.handleInputChange(event, "riskTitle")} value={this.state.riskTitle}/>
                    </div>
                </div>
                <div class="tr">
                    <div class="td label" style={{verticalAlign: 'top'}}>
                        Risk Statement
                    </div>
                    <div class="td data"  style={{verticalAlign: 'top'}}>
                        <textarea onKeyPress={(event) => this.handleInputChange(event, "riskStatement")} value={this.state.riskStatement}></textarea>
                    </div>
                </div>
                <div class="tr">
                    <div class="td label"  style={{verticalAlign: 'top'}}>
                        Context
                    </div>
                    <div class="td data"  style={{verticalAlign: 'top'}}>
                        <textarea onKeyPress={(event) => this.handleInputChange(event, "riskContext")} value={this.state.riskContext}></textarea>
                    </div>
                </div>
                <div class="tr">
                    <div class="td label"  style={{verticalAlign: 'top'}}>
                        Closure Criteria
                    </div>
                    <div class="td data"  style={{verticalAlign: 'top'}}>
                        <textarea onKeyPress={(event) => this.handleInputChange(event, "closureCriteria")} value={this.state.closureCriteria}></textarea>
                    </div>
                </div>
                <div class="tr">
                    <div class="td label"  style={{verticalAlign: 'top'}}>
                        Owner Notes
                    </div>
                    <div class="td data"  style={{verticalAlign: 'top'}}>
                        <textarea onKeyPress={(event) => this.handleInputChange(event, "ownerNotes")} value={this.state.ownerNotes}></textarea>
                    </div>
                </div>
                <div class="tr">
                    <div class="td label" style={{verticalAlign: 'top'}}>
                        Approver Comments
                    </div>
                    <div class="td data"  style={{verticalAlign: 'top'}}>
                        <textarea onKeyPress={(event) => this.handleInputChange(event, "approverComments")} value={this.state.approverComments}></textarea>
                    </div>
                </div>
            </div>
        );
    }
}
Maradox
  • 620
  • 2
  • 13
  • Maradox, first of all, thank you so much, I really appreciate your help. My text input textbox elements only allow editing even with the provided code if I use defaultValue, BUT, I then retain the same value in the textbox each time I navigate records. I wonder if I can force update somehow on defaultValue. defaultValue allows for updating, but keeps the same data for all records irrespective of which record. using value updates all appropriately on navigation but prevents updating on key press, very strange, any suggestions? – Vahe May 31 '22 at 02:35
  • 1
    I think that it will help you - https://stackoverflow.com/questions/30727837/react-change-input-defaultvalue-by-passing-props – Maradox May 31 '22 at 15:19
  • Adding a key property to my parent form solved the issue. Thank you so much. `key={this.state.risk.riskid}` This was referenced from the top answer from the provided link. https://stackoverflow.com/a/41962233/1691103 – Vahe May 31 '22 at 15:43