简体   繁体   English

在对象上反应和打字稿 useState

[英]react and typescript useState on a object

I have a type product within a React component:我在 React 组件中有一个类型product

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

in which my component I wish to change the values through a input box:在我的组件中,我希望通过输入框更改值:

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

I thought by adding ...product it would copy over all the same values within product and just change the value I wanted to but that didn't seem to work.我想加入...product将在副本中所有相同值product ,只是改变我想,但似乎并没有工作的价值。 It would set a new product object although it would just rewrite the whole content of the object with the only the most recent entered input.它会设置一个新的产品对象,尽管它只会用最近输入的输入重写对象的全部内容。

I then attempted a different approach with an interface where:然后我尝试了一种不同的接口方法,其中:

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

and

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

and using a similar state change as I have shown previously, but alas that only occurred in another new bug (I guess I'm not sure how to properly use an interface in react).并使用与我之前展示的类似的状态更改,但可惜只发生在另一个新错误中(我想我不确定如何在反应中正确使用接口)。

Apart from supplying the methods for the onChange events on the inputs, you will need to specify the value as well.除了为输入的onChange事件提供方法之外,您还需要指定value For instance,例如,

value={product.name}

In addition, I am not sure why is the product state deeply nested, as there is no need to go one level deeper in this scenario, This will reduce the complexity when you need to update the product state on each of the onChange events.另外,我不确定为什么product状态是深度嵌套的,因为在这种情况下不需要更深一层,这将降低您需要在每个onChange事件上更新产品状态时的复杂性。 You only need to spread the current product state, followed by updating the property with the new values.您只需要传播当前产品状态,然后使用新值更新属性。 For instance,例如,

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

In addition, when it comes to typing the product state, there is no need to assert is as TProduct .此外,在输入产品状态时,无需断言 is as TProduct Given that the properties may be undefined, you can keep the following interface,鉴于属性可能未定义,您可以保留以下接口,

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

And set the typings for product as Partial<TProduct> .并设置分型为productPartial<TProduct>

Last but not least, if you are working with the newer versions of React, it will be sufficient to type your component as React.FC .最后但并非最不重要的一点是,如果您正在使用较新版本的 React,将您的组件输入为React.FC就足够了。

This is how your component should look like.这就是您的组件的外观。

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

You want to spread into a new object and then override the properties you need eg您想传播到一个新对象中,然后覆盖您需要的属性,例如

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

Although, given you are setting just product you might want to not making it a nested property of the state and just making it the state itself.虽然,鉴于您只设置product您可能不希望将其设置为状态的嵌套属性,而只是将其设置为状态本身。

Try this:尝试这个:

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

This works well when you have an object in useState.当您在 useState 中有一个对象时,这很有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM