reactjs自定义组件输入值不会随着状态更改而更新

时间:2020-01-22 22:24:27

标签: javascript reactjs

我正在使用列表应用程序,但是组件无法正确更新时遇到问题。我从JSON文件中提取用户列表,并将其保存为状态。我正在使用上下文将状态和其他信息传递给我的不同组件。最小的组成部分是用户项目,分为可编辑的列表。这是我遇到问题的项目列表。

例如,我有两个不同的JSON文件:

    [{"userId": 81944,
        "listId": 1,
        "title": "testa",
        "items": [
            {
                "listItemId": 0,
                "product": "walnuts",
                "quantity": 1,
                "category": "Bakery",
                "unit": "Each",
                "cart": false
            },
            {
                "listItemId": 1,
                "product": "syrup",
                "quantity": 1,
                "category": "Beverages",
                "unit": "Each",
                "cart": true
            },
            {
                "listItemId": 2,
                "product": "cinnamon",
                "quantity": 6,
                "category": "Bakery",
                "unit": "Each",
                "cart": false
            },
            {
                "listItemId": 3,
                "product": "gabonzo beans",
                "quantity": 1,
                "category": "Canned Goods",
                "unit": "Each",
                "cart": true
            },
            {
                "listItemId": 4,
                "product": "diced tomatos",
                "quantity": 7,
                "category": "Produce",
                "unit": "Each",
                "cart": false
            },
            {
                "listItemId": 5,
                "product": "milk",
                "quantity": 1,
                "category": "Dairy",
                "unit": "Oz",
                "cart": false
            },
            {
                "listItemId": 6,
                "product": "salmon",
                "quantity": 3,
                "category": "Meat",
                "unit": "Lb",
                "cart": false
            }]},{
        "userId": 78863,
        "listId": 4,
        "title": "testd",
        "items": [
            {
                "listItemId": 0,
                "product": "half and half",
                "quantity": 1,
                "category": "Dairy",
                "unit": "Each",
                "cart": false
            },
            {
                "listItemId": 1,
                "product": "Blue Cheese",
                "quantity": 1,
                "category": "Dairy",
                "unit": "Each",
                "cart": false
            },
            {
                "listItemId": 2,
                "product": "Garlic",
                "quantity": 1,
                "category": "Produce",
                "unit": "Each",
                "cart": false
            },
            {
                "listItemId": 3,
                "product": "Chestnuts",
                "quantity": 1,
                "category": "Other",
                "unit": "Each",
                "cart": false
            },
            {
                "listItemId": 4,
                "product": "Balsamic Vinegar",
                "quantity": 1,
                "category": "Other",
                "unit": "Each",
                "cart": false
            },
            {
                "listItemId": 5,
                "product": "Onions",
                "quantity": 1,
                "category": "Produce",
                "unit": "Each",
                "cart": false
            },
            {
                "listItemId": 6,
                "product": "Flax Seed",
                "quantity": 1,
                "category": "others",
                "unit": "Each",
                "cart": false
            },
            {
                "listItemId": 7,
                "product": "Plantains",
                "quantity": 1,
                "category": "Produce",
                "unit": "Each",
                "cart": false
            }]}]

在我的应用程序中,我有一个对话框,允许我在列表之间切换。然后,我获取列表并将其传递给要在屏幕上绘制的自定义组件。

import React, {useState,useEffect} from 'react';



const Card=(props)=>{
    //console.log('prop');
    const [cart, setCart] = useState(props.cart);
    const [Product, setProduct] = useState(props.item);
    const [Quantity, setQuantity] = useState(props.units);

    // useEffect(()=>{
    //  setProduct(props.item)
    //  setQuantity(props.units)
    //  setCart(props.cart);

    // },[])
    console.log(props)
    return (
        <li key={props.value}>
            <div>
                <input type="checkbox" checked={cart} onChange={(e)=>{props.cartChange(e.target)}}/>
            </div>
            <div>
                <input id={'product '+props.value} className='update' 
                type='text' value={Product} 
                onChange={(e)=>setProduct(e.target.value)}
                 />
                <br/>
                <input id='quantityValue' className='update' 
                type='number' value={Quantity} 
                onChange={(e)=>setQuantity(e.target.value)}
                 />
                <span id='quantityType' className='update'>{props.unitType}</span>
            </div>
            <div>
                <button id='save-button' type='button' 
                onClick={(e)=>{props.change(Product,Quantity,props.value)}}>&#10003; save</button>
                <button id='delete-button' type='button'>&#10007; delete</button>
            </div>
        </li>
    )
}
export default Card;

这是调用自定义组件的代码。您会看到我是从array.map()调用的,这些数组很好,并且其中包含正确的信息。

import React, {useContext,useEffect} from 'react';
import {DataContext} from '../../../context/test/DataContext'
import Card from './ItemCard';

const update=(x)=>{
    console.log(x)
}

const List = () =>{
    const {listId} = useContext(DataContext);
    const {userItemList} = useContext(DataContext);
    const {GetItemList} = useContext(DataContext);
    const {ListSplit} = useContext(DataContext);
    const {foundList} = useContext(DataContext);
    const {findList} = useContext(DataContext);
    const {Updater} = useContext(DataContext);
    const {cartUpdater} = useContext(DataContext);
    useEffect(()=>{
        GetItemList();
    },[listId])
    useEffect(()=>{
        ListSplit();
    },[userItemList])
    // console.log(findList);
    // console.log(foundList);

    return(
        <div>
            <p>To find:</p>
            <ul>
            {findList.map((item,index)=><Card key={item.listItemId} index={index}
                value={item.listItemId} cart={item.cart} item={item.product} 
                units={item.quantity} unitType={item.unit} 
                cartChange={cartUpdater} change={Updater} />)}
            </ul>
            <p>Found:</p>
            <ul>
            {foundList.map((item,index)=><Card key={item.listItemId} index={index}
                value={item.listItemId} cart={item.cart} item={item.product} 
                units={item.quantity} unitType={item.unit} 
                cartChange={cartUpdater} change={Updater} />)}
            </ul>
        </div>
    )
}
export default List;

每次切换此设置时,我注销的控制台道具都会正确更改。另外,如果我查看开发工具(chrome)中的组件,我会看到状态应该是正确的,但是我在屏幕上看到的是不正确的。例如第二个项目是肉桂,如果我切换到第二个列表,则应该是蓝纹奶酪。道具随状态变化,但我在屏幕上看到的仍然是肉桂。

我知道我可能没有清楚地解释它,但是下面是我在说什么的屏幕截图。

enter image description here

1 个答案:

答案 0 :(得分:0)

您已接近注释掉的代码。由于您将道具设置为状态(这是一个坏主意,我将在底部讨论),因此您的awk -v G="$g" -v theta="$theta_vs" -v z="$z_s" '{R=0; if($12 || $13) R=((G/theta)*($11-theta)*($8-z))/(($12^2)+($13^2)); print $0,R }' Input_file 仅在初始状态下设置状态。您想观看这些道具并在更新时进行更新。

useState

useEffect(() => { setProduct(props.item) setQuantity(props.units) setCart(props.cart); }, [props.item, props.units, props.cart]); 观察数组中的项目以了解是否应该触发。

作为旁注-为状态分配道具是一个坏主意,您已经知道了原因-它们不会自动更新。您应该将这些道具放置在父项上,然后将它们作为道具传递下来并直接使用。您也可以将传承者作为道具传下来,从而可以更新父项。

This article,在引用基于类的React组件时,如果您希望阅读它,可能会提供更多信息。

useEffect
const { useState } = React;

const initialItems = [
  {
    listItemId: 1,
    product: 'syrup',
    quantity: 1,
    category: 'Beverages',
    unit: 'Each',
    cart: true,
  },
  {
    listItemId: 2,
    product: 'cinnamon',
    quantity: 6,
    category: 'Bakery',
    unit: 'Each',
    cart: false,
  },
  {
    listItemId: 3,
    product: 'garbanzo beans',
    quantity: 1,
    category: 'Canned Goods',
    unit: 'Each',
    cart: true,
  },
];

const Parent = () => {
  const [items, setItems] = useState(initialItems);

  const updateProduct = listItemId => (e) => {
    setItems(items.map((item) => {
      if (item.listItemId === listItemId) {
        return { ...item, product: e.target.value };
      }

      return item;
    }));
  };

  const updateQuantity = listItemId => (e) => {
    setItems(items.map((item) => {
      if (item.listItemId === listItemId) {
        return { ...item, quantity: e.target.value };
      }

      return item;
    }));
  };

  return (
    <div>
      <div style={{ width: "50%" }}>
        All Items - (this state lives inside the parent component)
      </div>
      <div>
        {items.map(item => (
          <div>
            <div>
              Product - {item.product}
            </div>
            <div>
              Quantity - {item.quantity}
            </div>
          </div>
        ))}
      </div>
      <div style={{ width: "50%" }}>
        {items.map(item => (
          <Child item={item} updateQuantity={updateQuantity} updateProduct={updateProduct} />
        ))}
      </div>
    </div>
  );
};

const Child = ({ item, updateQuantity, updateProduct }) => {
  return (
    <div>
      <div>
        <span>
          Product -
        </span>
        <span>
          <input value={item.product} onChange={updateProduct(item.listItemId)} />
        </span>
      </div>
      <div>
        <span>
          Quantity -
        </span>
        <span>
          <input value={item.quantity} onChange={updateQuantity(item.listItemId)} />
        </span>
      </div>
    </div>
  );
};

ReactDOM.render(
  <Parent />,
  document.getElementById('root')
);

上面的一个小例子。父组件保存项目的状态,并在每个项目上进行映射以创建子组件。这个例子在边缘有些粗糙。您可以执行一些操作,例如在每个输入中添加<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="root"></div>data-id来简化更新功能,或者使用name来提升这种逻辑,但我认为这样做可以使您正确处理方向。