在MS Edge的React应用程序中调用setState后,输入不会更新

时间:2019-08-22 11:10:24

标签: reactjs microsoft-edge react-devtools

我创建了一个React应用。它可以在IE,Opera,Chrome,FF中正常运行。状态更新后在Edge中呈现一个组件时出现问题。我无法使用Chrome的React Devtools帮助自己,因为它在这里应该都能正常工作。

我的组件是两个输入字段的组合。一个是数字输入,可以由用户操纵,另一个是显示相同的数字值,但格式设置为货币字符串。当用户单击该字段时,具有格式化值的字段将隐藏并显示未格式化的输入字段。当用户离开可编辑输入时,隐藏的之前输入会再次显示。

由于我希望每次触发onchange事件时状态都会改变,因此其他输入也会在每个onchange上更新。 这是因为它是隐藏的吗?

这是代码,我试图尽可能简化它:

class MasterComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            Rows: [
                { Id: 1, Name: 'Row 1', Price: 11 },
                { Id: 2, Name: 'Row 2', Price: 21 },
                { Id: 3, Name: 'Row 3', Price: 13 }
            ]
        }
        this.changeObjectValue = this.changeObjectValue.bind(this);
    }
    render() {
        return <MCVE changeObjectValue={this.changeObjectValue} rows={this.state.Rows}></MCVE>
    }

    changeObjectValue(rowId, propertyName, value) {
        // define which list user wants to change
        let list = this.state['Rows'];
        let changedList = [];
        // change value
        list.forEach(element => {
            if (element.Id == rowId) {
                element[propertyName] = value;
            }
            changedList.push(element);
        });
        // dynamically set objct name frmo parameters
        this.setState({ Rows: changedList });
    }
}


class MCVE extends React.Component {
    render() {
        return <table>
            <thead>
                <tr>
                    <th>Id</th>
                    <th>Name</th>
                    <th>Price</th>
                </tr>
            </thead>
            <tbody>
                {this.props.rows.map((r, index) =>
                    <tr key={r.Id}>
                        <td>
                            <input readOnly value={r.Id}></input>
                        </td>
                        <td><input name="Name" onChange={event => this.changeInput(event, r.Id)} value={r.Name}></input></td>
                        <td>
                            <input name="Price" className="edit" type="hidden"  onBlur={event => toggleEditDisplay(event)} onChange={event => this.changeInput(event, r.Id)} value={r.Price}></input>
                            <input name="Price" className="display" readOnly onClick={event => toggleEditDisplay(event)} value={formatMoney(r.Price)}></input>
                        </td>
                    </tr>
                )}
            </tbody>
        </table>
            ;
    }
    changeInput(event, rowId) {
        let propertyName = event.target.name;
        this.props.changeObjectValue(
            rowId,
            propertyName,
            event.target.value);
    }
}

function toggleEditDisplay(event) {
    let el = event.target;

    // if has class 'edit' else has class 'display'    
    if (el.className.split(/\s+/).filter(e => e == 'edit').length > 0) {
        let elToToggle = el.parentElement.getElementsByClassName('display')[0];
        el.type = "hidden";
        elToToggle.type = "text";
    }
    else {
        let elToToggle = el.parentElement.getElementsByClassName('edit')[0];
        el.type = "hidden";
        elToToggle.type = "number";
    }
}
function formatMoney(amount, decimalCount = 2, decimal = ",", thousands = ".", currencySymbol = '€', ignoreCurrencySymbol = false) {
    try {
        decimalCount = Math.abs(decimalCount);
        decimalCount = isNaN(decimalCount) ? 2 : decimalCount;

        const negativeSign = amount < 0 ? "-" : "";

        let i = parseInt(amount = Math.abs(Number(amount) || 0).toFixed(decimalCount)).toString();
        let j = (i.length > 3) ? i.length % 3 : 0;

        return negativeSign + (j ? i.substr(0, j) + thousands : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousands) + (decimalCount ? decimal + Math.abs(amount - i).toFixed(decimalCount).slice(2) : "") + (ignoreCurrencySymbol ? "" : currencySymbol);
    } catch (e) {
        console.log(e)
    }
};

ReactDOM.render(<MasterComponent />, document.getElementById('app'));

最低HTML:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
    </head>

    <body>  
        <div id="app"></div>
        <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
        <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>

        <script src="reactScript.js"></script>
    </body>    
</html>

1 个答案:

答案 0 :(得分:1)

经过测试,问题似乎与type="hidden"有关,我们可以修改代码并使用CSS display属性来隐藏或显示输入元素。请检查以下步骤:

  1. 从第一个输入TexBox中删除“ type =“ hidden””。
  2. 在index.css文件中添加以下CSS样式:

    .edit{
      display:none;
    }
    
  3. 修改toggleEditDisplay函数:

    function toggleEditDisplay(event) {
      let el = event.target;
    
      // if has class 'edit' else has class 'display'    
      if (el.className.split(/\s+/).filter(e => e == 'edit').length > 0) {
          let elToToggle = el.parentElement.getElementsByClassName('display')[0];
          el.style.display ='none';
          elToToggle.type = "text";
          elToToggle.style.display ='block';
      }
      else {
          let elToToggle = el.parentElement.children[0];
          //el.type = "hidden";
          el.style.display ='none';
          elToToggle.type = "number";
          elToToggle.style.display ='block';
      }
      el.focus();
    }
    

在Edge浏览器中的结果如下:

enter image description here