React Hooks useState() with Object

前端 未结 9 1684
猫巷女王i
猫巷女王i 2020-12-02 06:04

What is the correct way of updating state, is a nested object, in React with Hooks?

export Example = () => {
  const [exampleState, setExampleState] = use         


        
相关标签:
9条回答
  • 2020-12-02 06:38

    If anyone is searching for useState() hooks update for object

    - Through Input
    
            const [state, setState] = useState({ fName: "", lName: "" });
            const handleChange = e => {
                const { name, value } = e.target;
                setState(prevState => ({
                    ...prevState,
                    [name]: value
                }));
            };
    
            <input
                value={state.fName}
                type="text"
                onChange={handleChange}
                name="fName"
            />
            <input
                value={state.lName}
                type="text"
                onChange={handleChange}
                name="lName"
            />
       ***************************
    
     - Through onSubmit or button click
        
            setState(prevState => ({
                ...prevState,
                fName: 'your updated value here'
             }));
    
    0 讨论(0)
  • 2020-12-02 06:38

    I think best solution is Immer. It allows you to update object like you are directly modifying fields (masterField.fieldOne.fieldx = 'abc'). But it will not change actual object of course. It collects all updates on a draft object and gives you a final object at the end which you can use to replace original object.

    0 讨论(0)
  • 2020-12-02 06:52

    I leave you a utility function to inmutably update objects

    /**
     * Inmutable update object
     * @param  {Object} oldObject     Object to update
     * @param  {Object} updatedValues Object with new values
     * @return {Object}               New Object with updated values
     */
    export const updateObject = (oldObject, updatedValues) => {
      return {
        ...oldObject,
        ...updatedValues
      };
    };
    

    So you can use it like this

    const MyComponent = props => {
    
      const [orderForm, setOrderForm] = useState({
        specialities: {
          elementType: "select",
          elementConfig: {
            options: [],
            label: "Specialities"
          },
          touched: false
        }
      });
    
    
    // I want to update the options list, to fill a select element
    
      // ---------- Update with fetched elements ---------- //
    
      const updateSpecialitiesData = data => {
        // Inmutably update elementConfig object. i.e label field is not modified
        const updatedOptions = updateObject(
          orderForm[formElementKey]["elementConfig"],
          {
            options: data
          }
        );
        // Inmutably update the relevant element.
        const updatedFormElement = updateObject(orderForm[formElementKey], {
          touched: true,
          elementConfig: updatedOptions
        });
        // Inmutably update the relevant element in the state.
        const orderFormUpdated = updateObject(orderForm, {
          [formElementKey]: updatedFormElement
        });
        setOrderForm(orderFormUpdated);
      };
    
      useEffect(() => {
          // some code to fetch data
          updateSpecialitiesData.current("specialities",fetchedData);
      }, [updateSpecialitiesData]);
    
    // More component code
    }
    

    If not you have more utilities here : https://es.reactjs.org/docs/update.html

    0 讨论(0)
  • 2020-12-02 06:54
    function App() {
    
      const [todos, setTodos] = useState([
        { id: 1, title: "Selectus aut autem", completed: false },
        { id: 2, title: "Luis ut nam facilis et officia qui", completed: false },
        { id: 3, title: "Fugiat veniam minus", completed: false },
        { id: 4, title: "Aet porro tempora", completed: true },
        { id: 5, title: "Laboriosam mollitia et enim quasi", completed: false }
      ]);
    
      const changeInput = (e) => {todos.map(items => items.id === parseInt(e.target.value) && (items.completed = e.target.checked));
     setTodos([...todos], todos);}
      return (
        <div className="container">
          {todos.map(items => {
            return (
              <div key={items.id}>
                <label>
    <input type="checkbox" 
    onChange={changeInput} 
    value={items.id} 
    checked={items.completed} />&nbsp; {items.title}</label>
              </div>
            )
          })}
        </div>
      );
    }
    
    0 讨论(0)
  • 2020-12-02 06:55

    Thanks Philip this helped me - my use case was I had a form with lot of input fields so I maintained initial state as object and I was not able to update the object state.The above post helped me :)

    const [projectGroupDetails, setProjectGroupDetails] = useState({
        "projectGroupId": "",
        "projectGroup": "DDD",
        "project-id": "",
        "appd-ui": "",
        "appd-node": ""    
    });
    
    const inputGroupChangeHandler = (event) => {
        setProjectGroupDetails((prevState) => ({
           ...prevState,
           [event.target.id]: event.target.value
        }));
    }
    
    <Input 
        id="projectGroupId" 
        labelText="Project Group Id" 
        value={projectGroupDetails.projectGroupId} 
        onChange={inputGroupChangeHandler} 
    />
    
    
    
    0 讨论(0)
  • 2020-12-02 06:57

    Generally you should watch out for deeply nested objects in React state. To avoid unexpected behavior, the state should be updated immutably. When you have deep objects, you end up deep cloning them for immutability, which can be quite expensive in React. Why?

    Once you deep clone the state, React will recalculate and re-render everything that depends on the variables, even though they haven't changed!

    So, before trying to solve your issue, think how you can flatten the state first. As soon as you do that, you will find beautiful tools that will help dealing with large states, such as useReducer().

    In case you thought about it, but are still convinced you need to use a deeply nested state tree, you can still use useState() with libraries like immutable.js and Immutability-helper. They make it simple to update or clone deep objects without having to worry about mutability.

    0 讨论(0)
提交回复
热议问题