对对象进行反应和打字稿useState

时间:2020-02-07 08:37:27

标签: reactjs typescript react-hooks

我在React组件中的类型为product

type TProduct = {
  name: string,
  price: string,
  stock: string
}

在我的组件中,我希望通过输入框更改值:

const AddProductCard: React.SFC = () => {
  const classes = useStyles();
  const [product, setProduct] = React.useState({ product:{} as TProduct})
  return (
     <input 
      onChange={e => setProduct({...product ,product: {name: e.target.value }})}
     />
     <input 
      onChange={e => setProduct({...product ,product: {stock: e.target.value }})}
     />
     <input 
      onChange={e => setProduct({...product ,product: {price: e.target.value }})}
     />
    )
  }

我认为,通过添加...product,它将复制product中所有相同的值,并且只是更改我想要的值,但这似乎不起作用。它将设置一个新的产品对象,尽管它只会使用最近输入的输入来重写对象的全部内容。

然后,我尝试使用以下接口的另一种方法:

interface IProduct {
  name: string;
  price:  string;
  stock: string;
}

const [product, setProduct] = React.useState<IProduct | undefined>(undefined);

,并且使用与我之前显示的状态更改类似的方法,但是可惜的是,这种更改仅发生在另一个新错误中(我想我不确定如何正确地在React中使用接口)。

3 个答案:

答案 0 :(得分:5)

除了为输入提供onChange事件的方法外,您还需要指定value。例如,

value={product.name}

此外,我不确定为什么product状态会嵌套得很深,因为在这种情况下不需要更深一层,这将降低您需要更新产品状态时的复杂性每个onChange事件。您只需要传播当前产品状态,然后使用新值更新属性即可。例如,

setProduct({
  ...product, 
  name: e.target.value 
});

此外,在输入产品状态时,无需断言为TProduct。鉴于属性可能未定义,您可以保留以下接口,

interface TProduct {
  name: string;
  price:  string;
  stock: string;
}

并将product的类型设置为Partial<TProduct>

最后但并非最不重要的一点是,如果您正在使用React的较新版本,则将组件键入为React.FC就足够了。

这就是您的组件的外观。

const AddProductCard: React.FC = () => {
  const classes = useStyles();
  const [product, setProduct] = React.useState<Partial<TProduct>>({});

  return (
     <input 
      value={product.name || ''}
      onChange={e => setProduct({...product, name: e.target.value })}
     />
     <input 
      value={product.stock || ''}
      onChange={e => setProduct({...product, stock: e.target.value })}
     />
     <input 
      value={product.price || ''}
      onChange={e => setProduct({...product, price: e.target.value })}
     />
    )
}

答案 1 :(得分:1)

您想扩展到新对象中,然后覆盖所需的属性,例如

setProduct({ 
  product: {
    ...product,
    name: e.target.value
  }
});

尽管如此,鉴于您只设置了product,您可能不希望使其成为状态的嵌套属性,而只是使其成为状态本身。

答案 2 :(得分:0)

尝试一下:

setProduct({
  ...product, 
  name: e.target.value 
}); 

当您在useState中有一个对象时,此方法效果很好。