您好,匿名用户

條件執行 react hook出錯 "React hook useState is called conditional"

0 投票

有时候设计一个元件的 props 和 state,会参考 React 的 <input> 的 props: "defaultValue", "value", "onChange" 来达成若 props 有则用 props,若没有则用 component 自有的 state。

可執行範例 [https://codesandbox.io/s/oo03...]

如果用 useState 来设计一个 <Counter> 的话,会报错误"React hook useState is called conditionally",如 React 文件 "" 所写,React Hook 依赖执行顺序 ( React relies on the order in which Hooks are called )。

useState <Counter />

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 元件我会这样写

class <CounterClass />


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>
    );
  }
}

请问这样的元件设计想法有什么错误吗?
在 React Hook 的写法中,该怎么改善比较好呢?

用户头像 提问 4 天 @ Nidalee 中士 (1,171 威望)
分享到:

1个回答

0 投票
 
最佳答案

剛剛從 stackoverflow 得到很好的回答

You could split your component into fully controlled and fully uncontrolled. Demo

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} />
  );
};

from:
https://stackoverflow.com/a/5...

用户头像 回复 4 天 @ 狐狸叫 下士 (736 威望)
选中 5月12日 @Nidalee
提一个问题:

相关问题

0 投票
1 回复 1 阅读
0 投票
0 回复 113 阅读
用户头像 提问 2017年 8月2日 @ 匿名用户
0 投票
1 回复 113 阅读
0 投票
0 回复 3 阅读

欢迎来到随意问技术百科, 这是一个面向专业开发者的IT问答网站,提供途径助开发者查找IT技术方案,解决程序bug和网站运维难题等。
温馨提示:本网站禁止用户发布与IT技术无关的、粗浅的、毫无意义的或者违法国家法规的等不合理内容,谢谢支持。

欢迎访问随意问技术百科,为了给您提供更好的服务,请及时反馈您的意见。
...