дополнительный контролируемый / неуправляемый компонент React с условными крючками React - PullRequest
2 голосов
/ 17 апреля 2019

IMO, React Hooks useState идеально подходит для шаблона для необязательного использования значения из реквизита или использования собственного состояния, но при использовании условного подключения ловушка показала некоторую ошибку.

Рабочий пример

Я пытался использовать хуки с условием, как показано ниже, но с ошибкой eslint React hook useState is called conditionally. Согласно этому объяснению из документа , React relies on the order in which Hooks are called.

const Counter = ({ value, onChange, defaultValue = 0 }) => {
  const [count, onCountChange] =
    typeof value === "undefined" ? useState(defaultValue) : [value, onChange];
  return (
    <div>
      {count.toString()}
      <button
        onClick={() => {
          onCountChange(count + 1);
        }}
      >
        +
      </button>
    </div>
  );
};
function App() {
  const [count, onCountChange] = useState(0);
  return (
    <div className="App">
      <div>
        Uncontrolled Counter
        <Counter />
      </div>
      <div>
        Controlled Counter
        <Counter value={count} onChange={onCountChange} />
      </div>
    </div>
  );
}

Как я могу использовать хуки для достижения той же функции, что и ниже класса Компонент?

class CounterClass extends React.Component {
  state = {
    value: this.props.defaultValue || 0
  };
  render() {
    const isControlled = typeof this.props.defaultValue === "undefined";
    const count = isControlled ? this.props.value : this.state.value;

    return (
      <div>
        {count.toString()}
        <button
          onClick={() => {
            isControlled &&
              this.props.onChange &&
              this.props.onChange(this.props.value + 1);
            !isControlled && this.setState({ value: this.state.value + 1 });
          }}
        >
          +
        </button>
      </div>
    );
  }
}

Или этот тип реквизита / состояния по желанию в одном компоненте неверен?

Я узнал об именах и идеях API "defaultValue", "value", "onChange" из компонента React JSX <input>.

1 Ответ

3 голосов
/ 17 апреля 2019

Вы можете разделить свой компонент на полностью контролируемый и полностью неуправляемый. Демо

const CounterRepresentation = ({ value, onChange }) => (
  <div>
    {value.toString()}
    <button
      onClick={() => {
        onChange(value + 1);
      }}
    >
      +
    </button>
  </div>
);

const Uncontrolled = ({ defaultValue = 0 }) => {
  const [value, onChange] = useState(defaultValue);
  return <CounterRepresentation value={value} onChange={onChange} />;
};

// Either use representation directly or uncontrolled
const Counter = ({ value, onChange, defaultValue = 0 }) => {
  return typeof value === "undefined" ? (
    <Uncontrolled defaultValue={defaultValue} />
  ) : (
    <CounterRepresentation value={value} onChange={onChange} />
  );
};
...