【问题标题】:Inputs in child component won't update when prop is changing in parent component当父组件中的道具发生变化时,子组件中的输入不会更新
【发布时间】:2018-03-26 12:34:34
【问题描述】:

我有一个购物清单应用,它分为以下两个组件:

我将这两个组件实现为:ShoppingList 和:ItemDetails 还有另一个组件:ListItem 表示一个项目行(带有编辑和删除按钮)。 ShoppinList 映射到 ListItems 数组。

我的 App 组件获取初始 items 数组并将其发送到 ShoppingList。 每次单击特定项目行中的编辑图标时,我都会在我的应用程序组件中设置 selectedItem 对象并呈现 ItemDetails 组件,将 selectedItem 传递给它,如下所示:

toggleDetailsPanel = (itemId) => (e) => {
    this.setState((prevState, props) => {
        return {
            selectedItem: (prevState.selectedItem && prevState.selectedItem.id === itemId) ? null : this.findItemById(itemId),
        };
    });
};

在 App 渲染函数中,我这样渲染它:

<div className={styles.details_outer_container}>
                    {this.state.selectedItem ? <ItemDetails handleSubmit={this.saveDetails} item={this.state.selectedItem}/> : null}
                </div>

每当单击保存按钮时,我都会在应用程序组件上运行一个函数来更新项目数组中的项目(saveDetails)。

现在我希望 ItemDetails 组件在每次单击不同项目行中的不同编辑图标时呈现新值,但输入值不会改变,只有标题正在呈现。

我尝试了所有找到的解决方案,包括 defaultValue,或使用 getValue() 函数设置值,或在输入上设置动态键,但没有任何帮助。

这是我的 ItemDetails 文件:

import React from 'react';
import PropTypes from 'prop-types';
import { Grid, Row, Col, input, Button } from 'react-bootstrap';
import styles from './styles.css';

export default class ProductDetails extends React.Component {

    static propTypes = {
        handleSubmit: PropTypes.func.isRequired,
        item: PropTypes.any.isRequired,
    };

    state = {
        id: this.props.item.id,
        name: this.props.item.name,
        quantity: this.props.item.quantity,
        price: this.props.item.price,
        description: this.props.item.description,
    };

    // Set appropriate property in state by input name
    handleInputChange = (e) => {
        this.setState({
            [e.target.name]: e.target.value,
        });
    };

    // Submit changed item to parent component
    handleDetailsSubmit = (e) => {
        this.props.handleSubmit(this.state);
        e.preventDefault();
    };

    render() {
        const item = this.props.item;
        const itemName = item.name.toUpperCase() || '';

        return (
            <div className={styles.details_container}>
                <div className="sub_header">
                    <span>{`${itemName} DETAILS`}</span>
                </div>
                <form className={styles.form_style}>
                    <p>
                        <label>{'Quantity'}</label>
                        <input type="text" ref="quantity" name="quantity" value={this.state.quantity}  onChange={this.handleInputChange} />
                    </p>
                    <p>
                        <label>{'Price'}</label>
                        <input type="text" ref="price" name="price" value={this.state.price} onChange={this.handleInputChange}/>
                    </p>
                    <p>
                        <label>{'Description'}</label>
                        <textarea rows={2} ref="description" name="description" value={this.state.description} onChange={this.handleInputChange}/>
                    </p>
                    <div className={styles.button_div}>
                        <Button onClick={this.handleDetailsSubmit} bsStyle="primary" bsSize="small">
                            {'Save'}
                        </Button>
                    </div>
                </form>
            </`enter code here`div>

        );
    }

}

我知道这是 React 处理表单的方式,但真的不知道如何解决它。 我真的很感激任何帮助:)

【问题讨论】:

  • AppComponent中this.state.selectedItem的值有变化吗?
  • 是的,确实如此。在我粘贴在这里的 toggleDetailsPanel 函数中

标签: javascript reactjs


【解决方案1】:

ProductDetails 组件仅从item 获取其初始值。从那时起,它都保持在状态。所以当item发生变化时需要重置状态。

尝试添加如下内容:

componentWillReceiveProps( newProps ) {
  if ( this.props.item !== newProps.item ) {
    this.setState( {
      id: newProps.item.id,
      name: newProps.item.name,
      quantity: newProps.item.quantity,
      price: newProps.item.price,
      description: newProps.item.description,
    } )
  }
}

【讨论】:

  • 谢谢!做到了。但是我认为孩子道具的变化应该会导致重新渲染,因此状态将通过“state = { ... } 初始设置重新初始化。所以我错了吗?
  • 你并没有完全错。重新渲染意味着再次运行render 方法,因此如果您在渲染方法中使用道具,它将响应更改。您的状态的初始值是在类本身中设置的,或者在 constructor 方法中设置,该方法在您实例化类时运行一次(通过运行 new SomeClass()
  • 啊,我明白了。那么将输入值绑定到组件的 props 不是更好的解决方案吗?
  • 你也可以这样做。但是您可能必须更改保存方法。所以我不会说它更好,只是一种不同的方法。
  • 为什么我必须更改保存方法?在所有输入 onChange 方法中,我正在更新状态中的相应属性,并且在保存时,我正在发送与输入保持同步的状态对象。所以我认为将输入绑定到道具可能会更好。但我不确定这是不是最佳做法。
猜你喜欢
  • 2018-07-02
  • 1970-01-01
  • 2021-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-08
相关资源
最近更新 更多