【问题标题】:How to handle the state of multiple inputs and change their state from the parent?如何处理多个输入的状态并从父级更改它们的状态?
【发布时间】:2020-06-29 08:48:58
【问题描述】:

我有一个具有编辑模式的自定义输入组件,我使用多个输入,我的目标是从输入中提取所有状态并将其放在父级上。

我设法为输入值做这件事,因为我为每个输入创建了一个 useState,但是我怎样才能为切换行为实现同样的事情。我想在每个输入旁边有一个按钮来切换输入的状态。(显示/隐藏输入)。

现在,当我按下编辑时,所有编辑布尔值都会被触发,因此所有输入都变得可见。

如何从父级一次切换一个输入,基本上我希望我的自定义组件纯粹用于演示,并且状态应该存在于父级上

例子:

const Parent = () => {
  const [value1, setValue1] = useState('')
  const [value2, setValue2] = useState('')
  const [value3, setValue3] = useState('') 


  const [editMode, setEditMode] = useState(false)

  return (
    <div>
      <ChildCustomInput value={value1} updateValue={setValue1} editMode={editMode} updateEditMode={setEditMode} />
      <ChildCustomInput value={value2} updateValue={setValue2} editMode={editMode} updateEditMode={setEditMode}/>
      <ChildCustomInput value={value3} updateValue={setValue3} editMode={editMode} updateEditMode={setEditMode}/>
    </div>
  )
}


const ChildCustomInput = (props)=> {
  // ref to update the input's value in the parent
  const textInputEl = useRef(null)

  // method to update the parent's values
  const updateComponentValue = () => {
    props.updateValue(textInputEl.current.value)
    props.updateEditMode(!props.editMode)
  }

  // Toggle Edit mode
  const changeEditMode = () => {
    props.updateEditMode(!props.editMode)
  }

  const renderEditView = () => {
    return (
      <div>
        <input ref={textInputEl}></input>
        <button onClick={updateComponentValue}>
          OK
        </button>
      </div>  
    )
  }


  const renderDefaultView = () => {
    return (
      <div>
        <div>
          {props.value}
        </div>

        <button onClick={changeEditMode}>
          EDIT
        </button>
      </div>
    )
  }


  return (
    <div>
    {
      props.editMode 
        ? renderEditView() 
        : renderDefaultView()
     }
    </div>
 )
} 



export default Parent;

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    您的每个输入(即editMode1、editMode2、editMode3)似乎都需要在父状态中使用editMode布尔值,并且每个ChildCutomInput应该使用自己的editModeX和setEditModeX而不是共享相同的布尔值。

    const Parent = () => {
      const [value1, setValue1] = useState('');
      const [value2, setValue2] = useState('');
      const [value3, setValue3] = useState('');
    
    
      const [editMode1, setEditMode1] = useState(false);
      const [editMode2, setEditMode2] = useState(false);
      const [editMode3, setEditMode3] = useState(false);
    
      return (
        <div>
          <ChildCustomInput value={value1} updateValue={setValue1} editMode={editMode1} updateEditMode={setEditMode1} />
          <ChildCustomInput value={value2} updateValue={setValue2} editMode={editMode2} updateEditMode={setEditMode2}/>
          <ChildCustomInput value={value3} updateValue={setValue3} editMode={editMode3} updateEditMode={setEditMode3}/>
        </div>
      )
    }
    

    【讨论】:

      【解决方案2】:

      对于这种情况,您应该有一个单独的状态来管理每个输入的切换属性。喜欢:

      const [value1EditMode, setValue1EditMode] = useState(false);
      const [value2EditMode, setValue2EditMode] = useState(false);
      

      每个输入等等。

      但我建议您使用useReducer 钩子,这样您只需使用一个reducer 即可管理整个子组件状态。你可以这样做:

      const initialState = {
        input1: {
          value: "",
          editMode: false
        },
        input2: {
          value: "",
          editMode: false
        },
        input3: {
          value: "",
          editMode: false
        }
      };
      
      function reducer(state, action) {
        switch (action.type) {
          case "CHANGE_VALUE":
            let newState = {
              ...state
            };
            newState[action.key].value = action.value;
            return newState;
          case "SET_EDIT_MODE":
            newState = {
              ...state
            };
            newState[action.key].editMode = action.editMode;
            return newState;
          default:
            throw new Error();
        }
      }
      
      const Parent = () => {
        const [state, dispatch] = useReducer(reducer, initialState);
      
        function updateValue(key, value) {
          dispatch({ type: "CHANGE_VALUE", value, key });
        }
      
        function updateEditMode(key, editMode) {
          dispatch({ type: "SET_EDIT_MODE", editMode, key });
        }
      
        return (
          <div>
            <ChildCustomInput
              value={state.input1.value}
              updateValue={value => {
                updateValue("input1", value);
              }}
              editMode={state.input1.editMode}
              updateEditMode={editMode => {
                updateEditMode("input1", editMode);
              }}
            />
            <ChildCustomInput
              value={state.input2.value}
              updateValue={value => {
                updateValue("input2", value);
              }}
              editMode={state.input2.editMode}
              updateEditMode={editMode => {
                updateEditMode("input2", editMode);
              }}
            />
            <ChildCustomInput
              value={state.input3.value}
              updateValue={value => {
                updateValue("input3", value);
              }}
              editMode={state.input3.editMode}
              updateEditMode={editMode => {
                updateEditMode("input3", editMode);
              }}
            />
          </div>
        );
      };
      
      

      这是一个工作示例:https://codesandbox.io/s/eloquent-hellman-8on6s?file=/src/Parent.js:52-1818

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-15
        • 1970-01-01
        • 1970-01-01
        • 2020-10-28
        相关资源
        最近更新 更多