ReactJS,从子组件改变状态

问题描述 投票:0回答:2

我有一个应用程序,可以从 API 获取一些数据。然后我将这些数据放入名为“数据”的数组中。然后这个“数据”数组被转换为名为“元素”的组件数组(具有由“数据”数组中的数据生成的子组件的数组)。当您按下“添加”按钮时,它会将新的空白数据添加到“数据”数组,然后使用 Efect cast updateElemets 函数使用此数据创建子组件并将此组件放入“元素”数组中。我通过按保存创建了 testfunc,它是 consol.log 的元素函数内容。同样的事情从子组件中执行 handleDelete 函数,但它抛出没有一个元素的数组。

在这里你可以试试看我在说什么:https://react-tw6smz.stackblitz.io

子组件:

const CategoryField = (props) => {
  const [label, setLabel] = useState(props.data.label);
  const [categoryId, setCategoryId] = useState(props.data.categoryId);
  const [description, setDescription] = useState(props.data.description);
  const [uniqueName, setUniqueName] = useState(props.data.uniqueName);

  return (
    <Row className="categoryBox">
      <Col xs={12}>
        <Row>
          <Col xs={12} className="categoryLabel">
            {label}
          </Col>
        </Row>
        <Row>
          <Col xs={4} className="categoryFieldTitle">
            categoryId:
            <input
              id="categoryId"
              onChange={(e) =>
                props.handleChange(e.target.value, props.id, e.target.id)
              }
              defaultValue={categoryId}
              className="categoryInput"
            />
          </Col>
          <Col xs={8} className="categoryFieldTitle">
            description:
            <input
              id="description"
              onChange={(e) =>
                props.handleChange(e.target.value, props.id, e.target.id)
              }
              defaultValue={description}
              className="categoryInput"
            />
          </Col>
        </Row>
        <Row>
          <Col xs={4} className="categoryFieldTitle">
            uniqueName:
            <input
              id="uniqueName"
              onChange={(e) =>
                props.handleChange(e.target.value, props.id, e.target.id)
              }
              defaultValue={uniqueName}
              className="categoryInput"
            />
          </Col>
          <Col xs={8} className="categoryFieldTitle">
            label:
            <input
              id="label"
              onChange={(e) => {
                setLabel(e.target.value);
                props.handleChange(e.target.value, props.id, e.target.id);
              }}
              defaultValue={label}
              className="categoryInput"
            />
          </Col>
        </Row>
        <Row>
          <Col xs={12}>
            <button
              className="categoryDeleteButton"
              onClick={(e) => props.handleDelete(props.id)}
            >
              Delete
            </button>
          </Col>
        </Row>
      </Col>
    </Row>
  );
};

父组件:

export default function App() {
  const [data, setData] = useState([]);
  const [elements, setElements] = useState();

  const addBlank = () => {
    let tmp = [...data];
    tmp.push({
      uniqueName: 'unique_name',
      categoryId: 'category_id',
      description: 'some description',
      label: 'Nazwa',
    });
    setData(tmp);
  };
  const handleChange = (change, id, type) => {
    let tmp = [...data];
    switch (type) {
      case 'categoryId':
        tmp[parseInt(id)].categoryId = change;
        break;
      case 'description':
        tmp[parseInt(id)].description = change;
        break;
      case 'uniqueName':
        tmp[parseInt(id)].uniqueName = change;
        break;
      case 'label':
        tmp[parseInt(id)].label = change;
        break;
    }
    setData(tmp);
  };
  const handleDelete = (id) => {
    console.log(elements);
  };

  const updateElements = () => {
    let tab = [];
    for (let i = 0; i < data.length; i++) {
      tab.push(
        <CategoryField
          key={data[i].uniqueName.toString() + '' + i}
          data={data[i]}
          id={i}
          handleChange={handleChange}
          handleDelete={handleDelete}
        />
      );
    }
    setElements(tab);
  };
  useEffect(() => {
    console.log('changed elements');
    console.log(elements);
  }, [elements]);

  useEffect(() => {
    // const reqOptions = {
    //   method: 'GET',
    //   headers: {
    //     'Content-Type': 'application/json',
    //   },
    // };
    // fetch('http://127.0.0.1:5050/test', reqOptions)
    //   .then((res) => res.json())
    //   .then((dt) => {
    //     setData(dt);
    //   });
    setData([
      {
        uniqueName: 'test_name',
        categoryId: '434324324',
        description: 'Some desc',
        label: 'Test Name',
      },
    ]);
  }, []);
  useEffect(() => {
    updateElements();
  }, [data]);

  const testfunc = () => {
    console.log(elements);
  };

  return (
    <div className="main">
      <Container>
        <Row className="sectionTitleBox">
          <Col xs={12} className="sectionTitle">
            Categories
          </Col>
        </Row>
        {elements}
        <Row>
          <Col xs={12}>
            <button onClick={testfunc}>Save</button>
            <button onClick={addBlank}>Add</button>
          </Col>
        </Row>
      </Container>
    </div>
  );
}

当您点击“添加”时,您可以看到添加新元素。 “保存”按钮用我的数据打印“元素”数组的内容。如果你按下“删除”按钮,它也会打印“元素”数组,但没有一个元素。

javascript reactjs components parent-child
2个回答
0
投票

好吧,我看到这是一个可以用useContext解决的问题,在组件之间共享状态和改变功能


0
投票

我唯一看到你的代码有问题的是

handleAction
函数实际上并没有改变数据状态。您只是记录当前数据,而不是更改它。

你的

handleAction
函数应该是这样的:

function parent() {
   const [data, setData] = useState([1,2,3])
   const handleAction = () => {
      // change data here accordingly
      setData(prev => [...prev, 1])
   }
   return (
      <div>
         <Child name="Do something" handleAction={handleAction}/>
         <button onClick={function that adds somethnig to data state}>Add somethnig to data state</button>
      </div>
   )
}
© www.soinside.com 2019 - 2024. All rights reserved.