admin 管理员组

文章数量: 1086019

I have two issues first how do I add/update the JSON items within a hook? The other being that React won't let me use the name stored from a previous JSON file.

I am open to other solutions, basically, as my input field are dynamically generated from a JSON file I'm unsure of the best way to store or access the data that's input into them I think storing them in a react hook as JSON and then passing them though as props to another ponent is probably best.

What I want to happen is onChange I would like the quantity value to be stored as a JSON object in a Hook here's my code:

React:

import React, { useState, useEffect } from 'react';
import Data from '../shoppingData/Ingredients';
import Quantities from '../shoppingData/Quantities';

const ShoppingPageOne = (props) => {
  //element displays
  const [pageone_show, setPageone_show] = useState('pageOne');

  //where I want to store the JSON data
  const [Quantities, setQuantities] = useState({});

  useEffect(() => {
    //sets info text using Json
    if (props.showOne) {
      setPageone_show('pageOne');
    } else {
      setPageone_show('pageOne hide');
    }
  }, [props.showOne]);

  return (
    <div className={'Shopping_Content ' + pageone_show}>
      //generates input fields from JSON data
      {Data.map((Ingredients) => {
        const handleChange = (event) => {
          // this is where I'd like the Hook to be updated to contain instances of the ingredients name and quantity of each
          setQuantities(
            (Ingredients.Name: { ['quantities']: event.target.value })
          );

          console.log(Quantities);
        };

        return (
          <div className="Shopping_input" key={Ingredients.Name}>
            <p>
              {Ingredients.Name} £{Ingredients.Price}
            </p>
            <input
              onChange={handleChange.bind(this)}
              min="0"
              type="number"
            ></input>
          </div>
        );
      })}
      <div className="Shopping_Buttons">
        <p onClick={props.next_ClickHandler}>Buy Now!</p>
      </div>
    </div>
  );
};

export default ShoppingPageOne;

JSON file:

//Json data for the shopping ingredients

export default [
    {
        Name: 'Bread',
        Price: "1.10",
    },

    {
        Name: 'Milk',
        Price: "0.50",
    },

    {
        Name: 'Cheese',
        Price: "0.90",
    },

    {
        Name: 'Soup',
        Price: "0.60",
    },

    {
        Name: 'Butter',
        Price: "1.20",
    }
]

I have two issues first how do I add/update the JSON items within a hook? The other being that React won't let me use the name stored from a previous JSON file.

I am open to other solutions, basically, as my input field are dynamically generated from a JSON file I'm unsure of the best way to store or access the data that's input into them I think storing them in a react hook as JSON and then passing them though as props to another ponent is probably best.

What I want to happen is onChange I would like the quantity value to be stored as a JSON object in a Hook here's my code:

React:

import React, { useState, useEffect } from 'react';
import Data from '../shoppingData/Ingredients';
import Quantities from '../shoppingData/Quantities';

const ShoppingPageOne = (props) => {
  //element displays
  const [pageone_show, setPageone_show] = useState('pageOne');

  //where I want to store the JSON data
  const [Quantities, setQuantities] = useState({});

  useEffect(() => {
    //sets info text using Json
    if (props.showOne) {
      setPageone_show('pageOne');
    } else {
      setPageone_show('pageOne hide');
    }
  }, [props.showOne]);

  return (
    <div className={'Shopping_Content ' + pageone_show}>
      //generates input fields from JSON data
      {Data.map((Ingredients) => {
        const handleChange = (event) => {
          // this is where I'd like the Hook to be updated to contain instances of the ingredients name and quantity of each
          setQuantities(
            (Ingredients.Name: { ['quantities']: event.target.value })
          );

          console.log(Quantities);
        };

        return (
          <div className="Shopping_input" key={Ingredients.Name}>
            <p>
              {Ingredients.Name} £{Ingredients.Price}
            </p>
            <input
              onChange={handleChange.bind(this)}
              min="0"
              type="number"
            ></input>
          </div>
        );
      })}
      <div className="Shopping_Buttons">
        <p onClick={props.next_ClickHandler}>Buy Now!</p>
      </div>
    </div>
  );
};

export default ShoppingPageOne;

JSON file:

//Json data for the shopping ingredients

export default [
    {
        Name: 'Bread',
        Price: "1.10",
    },

    {
        Name: 'Milk',
        Price: "0.50",
    },

    {
        Name: 'Cheese',
        Price: "0.90",
    },

    {
        Name: 'Soup',
        Price: "0.60",
    },

    {
        Name: 'Butter',
        Price: "1.20",
    }
]
Share Improve this question edited Dec 4, 2020 at 12:24 michael 4,1733 gold badges14 silver badges31 bronze badges asked Dec 4, 2020 at 12:16 lukeetlukeet 5111 gold badge7 silver badges27 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 2

Assuming your Quantities object is meant to look like:

{
    <Ingredient Name>: { quantities: <value> }
}

you need to change your handleChange to look like this

const handleChange = (event) => {
    setQuantities({
        ...Quantities,
        [Ingredients.Name]: {
            ...(Quantities[Ingredients.Name] ?? {}),
            quantities: event.target.value
        }
    });
};

Explanation

When updating state in React, it is important to replace objects rather than mutating existing ones, as this is what tells React to rerender ponents. This is monly done using the spread operator, and with array functions such as map and filter. For example:

const myObject = { test: 1 };
myObject.test = 2; // Mutates existing object, wrong!
const myNewObject = { ...myObject, test: 2 }; // Creates new object, good!

Note the spread operator doesn't operate below the first level, what I mean by that is, objects within the object will be copied by reference, for example:

const myObject = { test : { nested: 1 } };
const myObject2 = { ...myObject };
myObject2.test.nested = 2;
console.log(myObject.test.nested); // outputs 2

Also in my answer, I have used the nullish coalescing operator (??), this will return it's right operand if the left operand is null or undefined, for example:

null ?? 'hello'; // resolves to "hello"
undefined ?? 'world'; // resolves to "world"
"foo" ?? "bar"; // resolves to "foo"

In my answer I used it to fallback to an empty object if Quantities[Ingredients.Name] is undefined.

Finally, I used square brackets when using a variable as an object key as this causes the expression to be evaluated before being used as a key:

const myKey = 'hello';
const myObject = {
    [myKey]: 'world';
};
console.log(myObject); // { hello: 'world' }

本文标签: javascriptHow do I create a new JSON object inside a react hookStack Overflow