使用React Hooks切换对象中一项的值

时间:2019-09-10 12:51:54

标签: reactjs react-hooks react-props

在问题末尾查看更新

也请参阅第二次更新

我有一个包含两个项目的简单对象(尽管可能会增长到更多):

const initialValues = {

  noLabels: false,
  useFormik: false,
}

我现在想使用React Hooks来切换该对象中给定项目的值。这将起作用的方式是,我将检查是否设置了道具。如果设置了道具,那么我想将值切换为true。如果未设置,则将其保留为false。

例如:

<Form noLabels>
...
</Form>

这会将noLabels设置为true

我正试图弄清楚如何编写一个简单的函数来完成此操作,而无需写else if语句。

所以,我想要一个看起来像这样的简单函数:

const toggleValues = setValues(props.value = !props.value)

当然,prop.value不起作用。我想知道的是什么可行。我应该在setValues()函数中放置什么,以便可以切换对象中的相关项目?

更新

我的问题基于我正在创建的上下文。这是代码:

import React, { createContext, useState } from 'react'

export const FormContext = createContext()

const initialState = {
  noLabels: false,
  formik: false,
}
export const FormProvider = ({ children }) => {
  const [values, setValues] = useState(initialState)


  return (
    <FormContext.Provider value={{ ...values }}>
      {children}
    </FormContext.Provider>
  )
}

我想做的就是添加一个toggleValues函数-像这样:

import React, { createContext, useState } from 'react'

export const FormContext = createContext()

const initialState = {
  noLabels: false,
  formik: false,
}
export const FormProvider = ({ children }) => {
  const [values, setValues] = useState(initialState)

const toggleValues = setValues({...values, XXXXXXXX })

  return (
    <FormContext.Provider value={{ ...values, toggleValues }}>
      {children}
    </FormContext.Provider>
  )
}

我正在尝试找出要输入XXXXXXXX的内容。

第二次更新


我正在尝试找到一种解决方案,该解决方案不需要要求我指定对象键的名称。而是会自动查看Form组件上的props名称,并对照对象的键检查它们。如果它们匹配,则将切换该项目。

3 个答案:

答案 0 :(得分:1)

您可以尝试使用useEffect,例如noLabels更改的副作用:

const initialValues = {
  noLabels: false,
  useFormik: false
};

const CustomForm = ({ noLabels, useFormik }) => {
  const [values, setValues] = useState(initialValues);

  useEffect(() => {
    setValues({ noLabels, useFormik });
  }, [noLabels, useFormik]);

  return <Checkbox checked={values.noLabels}>noLabels</Checkbox>;
};

export default function App() {
  const [labelIsOn, setLabelIsOn] = useState(true);
  return (
    <FlexBox>
      <CustomForm noLabels />
      <CustomForm noLabels={labelIsOn} />
      <Button onClick={() => setLabelIsOn(p => !p)}>Toggle Label Is On</Button>
    </FlexBox>
  );
}

Edit styled-antd-react-starter

答案 1 :(得分:0)

类似这样的事情应该适合您的情况

  const [ innitial, setInitial] = useState({
  noLabels: false,
  useFormik: false
  })

  function toggle() {
    setInitial(props ? {...innitial, noLabels: true} : {...innitial, noLabels: false})
  }


```

Then you can tie the toggle function to your form

答案 2 :(得分:0)

这是一种无需指定键即可在toggleValues函数中进行切换的方法。只需在调用toggleValues时传递要切换的键值即可。

我还创建了一个自定义钩子,并在其中添加了初始状态和toggleValues函数。分开逻辑。

View on CodeSandbox

const initialState = {
  noLabels: false,
  useFormik: false,
  toggleValues: () => {}
};

function useForm() {
  const [values, setValues] = useState(initialState);

  const toggleValues = name => {
    setValues(value => ({ ...value, ...{ [name]: !value[name] } }));
  };
  return [values, toggleValues];
}

const FormContext = createContext();

const FormProvider = ({ children }) => {
  const [values, toggleValues] = useForm();
  const { noLabels } = values;
  return (
    <FormContext.Provider
      value={{ ...values, toggleValues }}
    >
      {children(values, toggleValues)}
    </FormContext.Provider>
  );
};

function App() {
  return (
    <FormProvider>
      {(values, toggleValues) => {
        const { noLabels } = values;
        console.log(values);
        return (
          <>
            <input
              type="checkbox"
              value={noLabels}
              onChange={() => toggleValues("noLabels")}
            />
            {noLabels || <label>noLabels</label>}
          </>
        );
      }}
    </FormProvider>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);