Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 带条件反应挂钩的可选受控/非受控反应组件_Reactjs_React Hooks - Fatal编程技术网

Reactjs 带条件反应挂钩的可选受控/非受控反应组件

Reactjs 带条件反应挂钩的可选受控/非受控反应组件,reactjs,react-hooks,Reactjs,React Hooks,在我看来,React-Hooks-useState非常适合模式选择使用props中的值或使用自己的状态,但是当我有条件地使用hook时,lint显示了一些错误 我尝试使用钩子,条件如下,但是使用eslint errorReact钩子useState被有条件地调用。根据这一点,React依赖于调用钩子的顺序 const Counter = ({ value, onChange, defaultValue = 0 }) => { const [count, onCountChange]

在我看来,React-Hooks-useState非常适合模式选择使用props中的值或使用自己的状态,但是当我有条件地使用hook时,lint显示了一些错误

我尝试使用钩子,条件如下,但是使用eslint error
React钩子useState被有条件地调用。根据这一点,
React依赖于调用钩子的顺序

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>
  );
}
const Counter=({value,onChange,defaultValue=0})=>{
常数[计数,计数变化]=
值的类型==“未定义”?使用状态(默认值):[value,onChange];
返回(
{count.toString()}
{
onCountChange(计数+1);
}}
>
+
);
};
函数App(){
const[count,onCountChange]=useState(0);
返回(
非受控计数器
受控计数器
);
}
如何使用钩子来实现与类下组件相同的功能

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.Component{
状态={
值:this.props.defaultValue | | 0
};
render(){
const isControlled=typeof this.props.defaultValue==“未定义”;
const count=isControlled?this.props.value:this.state.value;
返回(
{count.toString()}
{
控制&&
这个。道具。改变&&
this.props.onChange(this.props.value+1);
!isControlled&&this.setState({value:this.state.value+1});
}}
>
+
);
}
}
或者这种道具/状态可选方式在一个组件中是错误的


我从React JSX
组件中学习了
“defaultValue”
“value”
“onChange”
API命名和思想。

您可以将组件分为完全受控和完全不受控

const CounterRepresentation=({value,onChange})=>(
{value.toString()}
{
onChange(值+1);
}}
>
+
);
const Uncontrolled=({defaultValue=0})=>{
const[value,onChange]=使用状态(defaultValue);
返回;
};
//可以直接使用表示法,也可以不受控制地使用表示法
常量计数器=({value,onChange,defaultValue=0})=>{
返回值的类型==“未定义”(
) : (
);
};

好问题!我认为这可以通过钩子来解决,方法是使
useState
调用成为无条件的,并且只使部分成为有条件的,在这里您可以决定渲染哪个状态以及使用什么更改处理程序

我刚刚释放了一个钩子,解决了这个问题:

用法:

import useOptionallyControlledState from 'use-optionally-controlled-state';
 
function Expander({
  expanded: controlledExpanded,
  initialExpanded = false,
  onChange
}) {
  const [expanded, setExpanded] = useOptionallyControlledState({
    controlledValue: controlledExpanded,
    initialValue: initialExpanded,
    onChange
  });
 
  function onToggle() {
    setExpanded(!expanded);
  }
 
  return (
    <>
      <button onClick={onToggle} type="button">
        Toggle
      </button>
      {expanded && <div>{children}</div>}
    </>
  );
}

// Usage of the component:

// Controlled
<Expander expanded={expanded} onChange={onExpandedChange} />
 
// Uncontrolled using the default value for the `initialExpanded` prop
<Expander />
 
// Uncontrolled, but with a change handler if the owner wants to be notified
<Expander initialExpanded onChange={onExpandedChange} />
从“使用可选控制状态”导入使用可选控制状态;
函数扩展器({
扩展:控制扩展,
initialExpanded=false,
一旦改变
}) {
const[expanded,setExpanded]=使用可选的受控状态({
controlledValue:controlledExpanded,
initialValue:initialExpanded,
一旦改变
});
函数onToggle(){
setExpanded(!expanded);
}
返回(
切换
{扩展&&{children}}
);
}
//组件的使用:
//控制
//使用'initialExpanded'属性的默认值不受控制
//不受控制,但如果所有者希望得到通知,则使用变更处理程序

通过使用一个钩子来实现这一点,您不必包装一个额外的组件,理论上,您可以将其应用于同一组件中的多个道具(例如,一个
组件,其中两个道具都可以随意控制)。

Wow!!我想这是我需要的正确答案。我认为这是一个使用
代表性组件
容器组件
(或智能/转储组件)概念的好例子。
import useOptionallyControlledState from 'use-optionally-controlled-state';
 
function Expander({
  expanded: controlledExpanded,
  initialExpanded = false,
  onChange
}) {
  const [expanded, setExpanded] = useOptionallyControlledState({
    controlledValue: controlledExpanded,
    initialValue: initialExpanded,
    onChange
  });
 
  function onToggle() {
    setExpanded(!expanded);
  }
 
  return (
    <>
      <button onClick={onToggle} type="button">
        Toggle
      </button>
      {expanded && <div>{children}</div>}
    </>
  );
}

// Usage of the component:

// Controlled
<Expander expanded={expanded} onChange={onExpandedChange} />
 
// Uncontrolled using the default value for the `initialExpanded` prop
<Expander />
 
// Uncontrolled, but with a change handler if the owner wants to be notified
<Expander initialExpanded onChange={onExpandedChange} />