0

What's the proper way, using TypeScript and React, to create a function that pushes a new object inside the array items ?

const [state, setState] = useState([
  {
    firstname: "William",
    items: [
      { name: "sword", damage: 100 },
      { name: "shield", damage: 50 },
    ],
  },
  {
    firstname: "Allison",
    items: [
      { name: "bow", damage: 70 },
      { name: "axe", damage: 120 },
    ],
  },
]);

const addNewItem = (newItem: object, CharacterIndex: number) => {

  // Push new item inside character's items.
  setState(newState)
};

return (
  <button onClick={() => addNewItem({ name: "dagger", damage: 50 }, 2)}>
    Add Item
  </button>
);

I have already done once using JavaScript, but with Typescript I often get some errors.

5
  • 1
    What errors, from what code? Give a minimal reproducible example - is React actually relevant here? Commented Jan 10, 2022 at 21:40
  • TypeError: Cannot assign to read only property 'items' of object '#<Object>' Commented Jan 10, 2022 at 21:48
  • Edit the question to provide a MRE, per the guidance in How to Ask. Commented Jan 10, 2022 at 21:49
  • Yes, i will do it, to be more clear Commented Jan 10, 2022 at 21:50
  • 1
    you want any not object - that said, these would be types (so you'd define an ItemType or whatever) and you don't want to mutate the array you'd push to a new one Commented Jan 10, 2022 at 21:50

2 Answers 2

1

You can Implement it the way you see it fits best.

const addNewItem = (newItem: object, CharacterIndex: number) => {

    //I would use this
    setState(state.map((elem: object, index: number) => {
        return index === characterIndex 
            ? { ...elem, items: [ ...elem.items, newItem ] }
            : elem;
    }));
};
Sign up to request clarification or add additional context in comments.

Comments

0

You should type your state and all your arrays

import { useState } from "react";
import "./styles.css";

const INITIAL_STATE = [
  {
    firstname: "William",
    items: [
      { name: "sword", damage: 100 },
      { name: "shield", damage: 50 }
    ]
  },
  {
    firstname: "Allison",
    items: [
      { name: "bow", damage: 70 },
      { name: "axe", damage: 120 }
    ]
  }
];

type Item = {
  name: string;
  damage: number;
};

type StateParams = {
  firstname: string;
  items: Item[];
};

export default function App() {
  const [state, setState] = useState<StateParams[]>(INITIAL_STATE);

  const addNewItem = (newItem: Item, characterIndex: number) => {
    const nextState = state.map((st, i) => {
      if (i === characterIndex) {
        return {
          firstname: st.firstname,
          items: [...st.items, newItem]
        };
      } else {
        return st;
      }
    });

    setState(nextState);

    console.log(state);
  };

  return (
    <button onClick={() => addNewItem({ name: "dagger", damage: 50 }, 1)}>
      Add Item
    </button>
  );
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.