我的一个组件实例化一个类并将其存储在状态中。 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()方法。
但是,当汽车的属性更新时,状态不会更新,有没有办法解决这个问题,以便状态能正确更新,或者这不是实现此目的的好方法?
答案 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 />
)
}
}