【问题标题】:Set prop values in callback在回调中设置道具值
【发布时间】:2016-12-12 11:03:03
【问题描述】:

我是 React 新手,想知道我是否在这里采取了正确的方法。

我有一个名为 <App /> 的个人资料页面和一个名为 <ContactDetails /> 的较低级别组件。我想将<ContactDetails /> 的状态存储在<App /> 上,所以我只需在一个地方为所有组件编写AJAX 逻辑。这种想法正确吗?

更具体地说,我感兴趣的是当用户更改输入时我将event.target.value 传递给<App /> 的方式是否正确?

联系方式:

import React from 'react';

class ContactDetails extends React.Component {
  render() {
    return (
      <div>
        <input value={this.props.contactDetails.email} onChange={event => this.props.onContactDetailsChange(Object.assign(this.props.contactDetails, {email: event.target.value}))} />
        <input value={this.props.contactDetails.firstName} onChange={event => this.props.onContactDetailsChange(Object.assign(this.props.contactDetails, {firstName: event.target.value}))} />
      </div>
    )
  }
}

export default ContactDetails;

应用:

import React from 'react';
import ReactDOM from 'react-dom';
import ContactDetails from './components/contact_details';

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      contactDetails: {
        email: 'a@a.com',
        firstName: ''
      }
    }
  }

  render() {
    return (
      <ContactDetails
        onContactDetailsChange={contactDetails => this.setState({ contactDetails })}
        contactDetails={this.state.contactDetails}
      />
    );
  }
}

ReactDOM.render(<App />, document.querySelector('.container'));

【问题讨论】:

  • 这段代码没有给你警告不要直接改变道具吗?
  • 谷歌浏览器控制台中没有警告
  • 我不知道如何运行它。您的联系方式组件返回 2 个未包含在封闭标记中的元素,我收到此错误。 Parsing error: Adjacent JSX elements must be wrapped in an enclosing tag.
  • 你的整体逻辑是对的,将值传回 App 并存储在 state 中。这段代码不应该运行。
  • 啊抱歉,我现在更新一下,我简化了代码以使其更易于阅读并且忘记放入包装器 div。

标签: javascript reactjs


【解决方案1】:

我会这样写你的解决方案:

import React from 'react';

// Class based component handles the logic
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      contactDetails: {
        email: 'a@a.com',
        firstName: '',
        lastName: '',
        mobile: ''
      }
    }
  }

  // One function to handle input changes
  handleContactDetailsChange = (value) => {
    // Object.assign() first argument is the target object.
    // Object.assign() returns the target object into contactDetails.
    // Second argument are the old contactDetails.
    // Third argument is the new input value. 
    // Because the third argument comes later it overwrites anything from
    // contactDetails that has the same key.
    this.setState({
      contactDetails: Object.assign({}, this.state.contactDetails, { ...value })
    });
    // { ...value } can also be written as just value, but this creates a copy.
  }

  render() {
    return (
     <ContactDetails
      onContactDetailsChange={this.handleContactDetailsChange}
      contactDetails={this.state.contactDetails}/>
    );
  }
}

// Stateless functional component.
// Takes props as an argument.
const ContactDetails = (props) => {
    // Pull of the two props we need from the props object(cleaner syntax).
    const { onContactDetailsChange, contactDetails } = props;
    return (
     <div>
       <input
        value={contactDetails.email}
        onChange={event => onContactDetailsChange({ email: event.target.value })}
       />
       <input
        value={contactDetails.firstName}
        onChange={event => onContactDetailsChange({ firstName: event.target.value })}
       />
     </div>
    )
};

export default App;

ContactDetails 通常在它自己的文件中。您还通过调用Object.assign(this.props.contactDetails, {firstName: event.target.value})修改了道具,因为目标是this.props.contactDetailsThe React philosophy is that props should be immutable and top-down.

【讨论】:

  • 您忘记将handleContactDetailsChange 绑定到this
  • 别忘了,ES6 箭头函数内置了这种行为。否则调用 this.setState() 甚至在我的代码中都不起作用。
  • 确实如此。我的眼睛滑过带有箭头功能的类属性:)
  • 出于性能原因,react 建议在构造函数方法this.handleContactDetailsChange = this.handleContactDetailsChange.bind(this); 处绑定“this”
  • 我认为它们的意思是,如果您在渲染方法中绑定它们,它们将在每次渲染时再次绑定,并且仅在构造函数中绑定一次。由于箭头函数属于类并且不在渲染中我认为不会有任何性能差异。
猜你喜欢
  • 2019-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-09
  • 1970-01-01
  • 2021-11-04
  • 2019-05-11
  • 1970-01-01
相关资源
最近更新 更多