React hooks: How do I update state on a nested object with useState()?

前端 未结 6 813
一个人的身影
一个人的身影 2021-02-08 13:43

I have a component that receives a prop that looks like this:

const styles = {
    font: {
        size: {
            value: \'22\',
            unit: \'px\'
           


        
相关标签:
6条回答
  • 2021-02-08 13:51

    This is your mistake

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

    To preserve the all font object values, you can do like this

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

    Or

    const onChange = (event) => {
        setStyle({ 
            ...style,
            font: {
                ...style.font, // Spread the font object to preserve all values
                align: event.target.value
            }
        });
    }
    
    0 讨论(0)
  • 2021-02-08 13:51

    you can update the styles in this manner

    onChange={(event) => {
        const s = {...styles};
        s.font.align = event.target.value;
        setStyle(s);
        console.log(style);
    }}
    
    0 讨论(0)
  • 2021-02-08 13:51

    Your code for default useState is invalid. You should write like below for default 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);
              }}
            />);
    

    Demo: check this demo with console.log.

    0 讨论(0)
  • 2021-02-08 13:53

    First: const { ...styling } = styles; is the same as: const styling = styles;

    But you may skip that altogether, just use [...] = useState(styles)

    setStyle() accepts a function which receives the current state, in your case style. So you may use the spread operator ... to create new object and add values to it.

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

    Above code uses Arrow function, this could also be written as a normal function, but probably easier to understand:

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

    Your console.log in setStyle displays current style, as changed style will be seen on next render. So I've moved the console.log before return.

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

    Here are some links to help you understand all that:

    • Spread operator: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
    • useState hook: https://reactjs.org/docs/hooks-state.html
    • Arrow functions: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
    0 讨论(0)
  • 2021-02-08 14:01

    If you have multiple values in a nested object, try this method below:

    setPost({
      ...post,
      postDetails: {
        ...post.postDetails,
        [event.target.name]: event.target.value,
      },
    });
    
    0 讨论(0)
  • 2021-02-08 14:07

    You need to use spread syntax to copy the font object properties too. Also while trying to update current state based on previous, use the callback pattern

    <RadioButtonGroup
      onChange={(event) => { 
        setStyle(prevStyle => ({
            ...prevStyle,
            font: { ...prevStyle.font, align: event.target.value }
        }));
        console.log(style);
      }}
    />
    
    0 讨论(0)
提交回复
热议问题