如何在更新状态的情况下使用 getDerivedStateFromProps?

How to use getDerivedStateFromProps in an update state situation?

我对代码的重构感到困惑。

我的组件是这样工作的 ==> 我将来自父组件的传入道具设置为子组件的状态。然后我就可以在组件中进行更新状态操作了。

这是我的 UNSAFE_componentWillReceiveProps 函数:

UNSAFE_componentWillReceiveProps = (nextProps) => {
    if (nextProps 
        && nextProps.actionToEdit 
        && nextProps.actionToEdit.statement
    ) {
        const regex = /@\w+/g;
        const found = nextProps.actionToEdit.statement.match(regex);
        this.setState({
            parameters: found
        });
    }
};

这是我的 getDerivedStateFromProps 功能:

static getDerivedStateFromProps(
    nextProps: ICustomActionModalProps, 
    prevState: ICustomActionModalState
) {
    if (nextProps 
        && nextProps.actionToEdit 
        && nextProps.actionToEdit.statement
    ) {
        const regex = /@\w+/g;
        const found = nextProps.actionToEdit.statement.match(regex);
        return {
            parameters: found
        };
    }
    return null; 
}

这是我的 onChange 函数:

onChange = (newValue, e) => {
    const regex = /@\w+/g;
    const found = newValue.match(regex);
    this.setState({ parameters: found });
};

当 onChange 起作用时,我意识到了一些事情。

==> 如果我使用 UNSAFE_componentWillReceiveProps,状态更新完美。因为当onChange函数每次都起作用时UNSAFE_componentWillReceiveProps不起作用。

然而,

==> 如果我使用 getDerivedStateFromProps,状态会更新为旧的道具。因为当 onChange 函数每次都起作用时 getDerivedStateFromProps 也起作用。

我只希望我的 getDerivedStateFromProps 功能能够像我的旧 UNSAFE_componentWillReceiveProps 功能一样工作。

我该怎么做? 谢谢

您所描述的 problem 可以通过使您的 Component 完全受控或完全不受控但使用钥匙来解决。

第一种方法可能如下所示:

// --- parent component: Parent.tsx
import { Child } from "./Child";

export class Parent extends React.Component<{}, { counter: number }> {
  state = { counter: 0 };

  render() {
    return (
      <div>
        <div>
          <button onClick={() => this.setState(({ counter }) => ({ counter: counter + 1 }))}>increase counter</button>
        </div>
        <Child
          parentCounter={this.state.counter}
          setParentCounter={(n) => this.setState({ counter: n })}
        />
      </div>
    );
  }
}

// --- child component : Child.tsx
type Props = { parentCounter: number; setParentCounter: (n: number) => void };

export class Child extends React.Component<Props> {
  render() {
    const { parentCounter, setParentCounter } = this.props;

    return (
      <>
        <div>parent counter: {parentCounter}</div>
        <button
          onClick={() => {
            setParentCounter(parentCounter + 1);
          }}
        >
          increase parent counter
        </button>
      </>
    );
  }
}

因此,不存在两种独立的状态:一种在父组件中,另一种在子组件中。唯一的状态存在于父组件中,子组件有 setter 属性,它可以用来改变父组件的状态。

第二种方法(带键的不受控制的组件)使用这样一个事实,即当 key 更改子组件时,它会从头开始重新呈现并失去其内部状态:

// --- Parent.tsx
import { Child } from "./Child";

export class Parent extends React.Component<{}, { counter: number }> {
  state = { counter: 0 };

  render() {
    const { counter } = this.state;

    return (
      <div>
        <div>parent counter: {counter}</div>
        <div>
          <button
            onClick={() =>
              this.setState(({ counter }) => ({ counter: counter + 1 }))
            }
          >
            increase parent counter
          </button>
        </div>
        <Child parentCounter={counter} key={`child-key-${counter}`} />
      </div>
    );
  }
}

// --- Child.tsx
type Props = { parentCounter: number };
type State = { childCounter: number };

export class Child extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props);

    this.state = { childCounter: props.parentCounter };
  }

  render() {
    return (
      <>
        <div>child counter {this.state.childCounter}</div>
        <button
          onClick={() => {
            this.setState(({ childCounter }) => ({
              childCounter: childCounter + 1
            }));
          }}
        >
          increase child counter
        </button>
      </>
    );
  }
}