React挂钩:如何使用useState()更新嵌套对象上的状态?

时间:2019-06-28 07:40:12

标签: javascript reactjs destructuring

我有一个组件可以接收如下所示的道具:

const styles = {
    font: {
        size: {
            value: '22',
            unit: 'px'
        },
        weight: 'bold',
        color: '#663300',
        family: 'arial',
        align: 'center'
    }
};

我正在尝试更新align属性,但是当我尝试更新对象时,我只用align属性替换了整个对象。

这是我的更新方式:

const { ...styling } = styles;
const [style, setStyle] = useState(styling);

return (
        <RadioButtonGroup
            onChange={(event) => {
                setStyle({ ...style, font: { align: event.target.value } });
                console.log(style);
            }}
        />);

当我console.log style时,我刚拿回{"font":{"align":"left"}}。 我希望看到整个对象具有align的更新值。我是解构的新手,所以我在这里做错了什么?

6 个答案:

答案 0 :(得分:3)

您还需要使用传播语法来复制字体对象属性。另外,在尝试根据先前状态更新当前状态时,请使用回调模式

 <RadioButtonGroup
        onChange={(event) => {
            setStyle(prevStyle => ({ ...prevStyle, font: { ...prevStyle.font, align: event.target.value } }));
            console.log(style);
        }}
    />);

答案 1 :(得分:1)

您可以通过这种方式更新样式

onChange={(event) => {
    const s = {...styles};
    s.font.align = event.target.value;
    setStyle(s);
    console.log(style);
}}

答案 2 :(得分:1)

如果嵌套对象中有多个值,请尝试以下方法:

setPost({
  ...post,
  postDetails: {
    ...post.postDetails,
    [event.target.name]: event.target.value,
  },
});

答案 3 :(得分:0)

您的默认useState代码无效。 对于默认的useState,您应该像下面这样写:

  const { ...styling } = styles;
  const [style, setStyle] = useState({ styling }); // styling should be use in {}

return (
        <RadioButtonGroup
          onChange={event => {
            setStyle({
              ...styling,
              font: { ...styling.font, align: event.target.value }
            });
            console.log(style);
          }}
        />);

演示: 使用console.log查看此演示。

Edit awesome-diffie-pflqz

答案 4 :(得分:0)

这是你的错误

setStyle({
    ...style,
    font: { align: event.target.value } // This code replace the font object
});

要保留所有font个对象值,您可以这样做

const onChange = (event) => {
    const s = {...style};
    s.font.align = event.target.value;
    setStyle(s);
}

const onChange = (event) => {
    setStyle({ 
        ...style,
        font: {
            ...style.font, // Spread the font object to preserve all values
            align: event.target.value
        }
    });
}

答案 5 :(得分:0)

第一: const { ...styling } = styles; 是相同的: const styling = styles;

但是您可以完全跳过,只需使用[...] = useState(styles)

setStyle()接受一个以您的案例样式接收当前状态的函数。 因此,您可以使用传播运算符...创建新对象并向其中添加值。

setStyle(style => ({ ...style, font: { ...style.font, align: event.target.value } ) ) );

以上代码使用Arrow函数,也可以将其编写为普通函数,但可能更易于理解:

setStyle( function (style) {
    return  {
        ...style,
        font: {
            ...style.font,
            align: 'center'
        }
    }
});

您在console.log中的setStyle显示当前样式,因为更改的样式将在下一个渲染中看到。因此,在退货前,我已经将console.log移了。

const [style, setStyle] = useState(styles);

console.log(style);

return (
        <RadioButtonGroup
            onChange={(event) => {
                setStyle(style => ({ ...style, font: { ...style.font, align: event.target.value } ) ) );
            }}
        />);

以下一些链接可帮助您了解所有内容: