skip to Main Content

I have a hook with objects in an array and I want to change the value of key test of the first object only.

const [Value, setValue] = useState([{test: 0}, {test: 0}]);

Also, I would like to be able to change a value from one to another at the click of a button, like toggle. For example to get only 0 or 1 on click on one button.

Could you please tell me how to do it?

2

Answers


  1. You can make a copy of the state in the callback of the set function.

    Then alter index 0 with the new value and return the copy.

    const { useState, useEffect } = React;
    
    const Example = () => {
    
        const [value, setValue] = useState([{test: 0}, {test: 0}]);
        
        useEffect(() => {
            setValue(p => {
                let d = [ ...p ];
                d[0].test = 420;
                return d;
            })
        }, []);
    
        return (
            <div>
                <h1>{'Example'}</h1>
                <em>{JSON.stringify(value)}</em>
            </div>
        )
    }
    ReactDOM.render(<Example />, document.getElementById("react"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
    <div id="react"></div>

    As requested, on a click event:

    const { useState, useEffect } = React;
    
    const Example = () => {
    
        const [value, setValue] = useState([{test: 0}, {test: 0}]);
        
        const updateFirstTestValue = () => {
            setValue(p => {
                let d = [ ...p ];
                d[0].test = d[0].test + 1;
                return d;
            })
        }
    
        return (
            <div>
                <h1>{'Example'}</h1>
                <button onClick={updateFirstTestValue}>Add 1 to 'test'!</button>
                <br />
                <em>{JSON.stringify(value)}</em>
            </div>
        )
    }
    ReactDOM.render(<Example />, document.getElementById("react"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
    <div id="react"></div>

    As requested, on a click event with hard-coded values:

    const { useState, useEffect } = React;
    
    const Example = () => {
    
        const [value, setValue] = useState([{test: 0}, {test: 0}]);
        
        const updateFirstTestValue = (to) => {
            setValue(p => {
                let d = [ ...p ];
                d[0].test = to;
                return d;
            })
        }
    
        return (
            <div>
                <h1>{'Example'}</h1>
                <button onClick={() => updateFirstTestValue(0)}>Set to 0</button>
                <button onClick={() => updateFirstTestValue(1)}>Set to 1</button>
                <br />
                <em>{JSON.stringify(value)}</em>
            </div>
        )
    }
    ReactDOM.render(<Example />, document.getElementById("react"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
    <div id="react"></div>

    As requested, on a click event with toggle between 2 values

    const { useState, useEffect } = React;
    
    const Example = () => {
    
        const [value, setValue] = useState([{test: 0}, {test: 0}]);
        
        const toggelFirstTestValue = (to) => {
            setValue(p => {
                let d = [ ...p ];
                d[0].test = (d[0].test === 0) ? 1 : 0;
                return d;
            })
        }
    
        return (
            <div>
                <h1>{'Example'}</h1>
                <button onClick={toggelFirstTestValue}>Toggle 0~1</button>
                <br />
                <em>{JSON.stringify(value)}</em>
            </div>
        )
    }
    ReactDOM.render(<Example />, document.getElementById("react"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
    <div id="react"></div>
    Login or Signup to reply.
  2. You could do this with immer lib which looks more clean and do normal array operations after that. As it under the hood creates copy of the original state and work on it.

    import React from "react";
    import { useImmer } from "use-immer";
    
    
    function App() {
      const [value, setValue] = useImmer ([{test: 0}, {test: 0}]);
      // Now set values as you do with normal JS operations
      setValue(draft => {
        draft[0].test = "newVal"
        draft[1].test = "anotherNewVa1";
      })
    }
    

    You don’t need to copy with this apprach by your self, and not need to be concious if you are mistakenly using mutating method like =[], push etc. You can here use any methods from Array objects.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search