反应状态侦听对象属性更改

时间:2019-07-31 01:14:57

标签: javascript reactjs class state

我的一个组件实例化一个类并将其存储在状态中。 Person类用于许多组件中。

// Car class
this.state = {
    driver: new Person(),
    passenger: new Person()
}

然后显示该人的位置

// Car class
render() {
    return (
        <div>
            <img src={this.state.driver.src} style={{left: this.state.driver.x, top: this.state.driver.y}} />
            <img src={this.state.passenger.src} style={{left: this.state.passenger.x, top: this.state.passenger.y}} />
            <span onClick={this.state.driver.moveRight}>Move Driver</span>
            <span onClick={this.state.passenger.moveRight}>Move Passenger</span>
        </div>
    )
}

正在移动moveRight函数

//Person class
moveRight() {
    this.x += 1;
}

这避免了在需要移动人员的所有组件中重写Person.moveRight()方法。

但是,当汽车的属性更新时,状态不会更新,有没有办法解决这个问题,以便状态能正确更新,或者这不是实现此目的的好方法?

2 个答案:

答案 0 :(得分:3)

如果您正考虑使用功能组件,这似乎是实现custom hook的完美用例。

创建一个usePerson挂钩,然后在您的Car组件中使用它。在这里,尝试一下:

import React, { useState } from "react";

function usePerson() {
  const [person, setPerson] = useState({
    x: 0,
    y: 0,
    src: "https://cdn2.iconfinder.com/data/icons/rcons-car/512/car-128.png"
  });

  function moveRight() {
    setPerson({
      ...person,
      x: person.x + 10
    });
  }

  return [person, moveRight];
}

export default usePerson;

在您的Car组件中:

import React, { Fragment } from "react";
import usePerson from "./usePerson";

function Car(props) {
  const [driver, moveRightDriver] = usePerson();
  const [passenger, moveRightPassenger] = usePerson();

  // console.log("Driver: ", driver);
  // console.log("Passenger: ", passenger);

  return (
    <Fragment>
      <img
        alt="Driver"
        src={driver.src}
        style={{ left: driver.x, top: driver.y }}
      />
      <img
        alt="Passenger"
        src={passenger.src}
        style={{ left: passenger.x, top: passenger.y }}
      />
      <button onClick={moveRightDriver}>Move Driver</button>
      <button onClick={moveRightPassenger}>Move Passenger</button>
    </Fragment>
  );
}

export default Car;

  

这是您推荐的Working CodeSandbox Sample


  

注意::图像似乎没有移动,但是如果取消注释console.log的注释,您会发现x确实在变化。因此,您可能需要纠正这种逻辑。

答案 1 :(得分:1)

您可以使用高阶组件范例。该建议与您尝试实现的UI不完全匹配,但使您更接近所需的功能。

值得注意的是,我将使每个Person组件(通过HOC范例)管理其自己的状态,而不是让该状态由呈现该组件的组件(即Car)管理。

const withMovement = RenderComponent => {
  return class extends Component {
     constructor() {
       super(props);
       this.state = { x = 0 }
     }

     moveRight = () => {
        const { x } = this.state; 
        this.setState({ x: x + 1 });
     }

     render() {
        return <RenderComponent moveRight={this.moveRight} xPosition={this.state.x} {...this.props} />
     }
  }
}

class Person extends Component {
   constructor() {
     super(props);
     // handle additional state here
   }

   render() {
     // Use xPosition props for display
     console.log('this.props.xPosition', this.props.xPosition);
     return (
       <button onClick={() => this.props.moveRight()} />
     )
   }
}

const Passenger = withMovement(Person);
const Driver = withMovement(Person);

class Car extends Component {
  constructor() {
     super(props);
   }

   render() {
      return (
        <Passenger />
        <Driver />
      )
   }
}