首页 > 解决方案 > React - 通过触发另一个组件中的事件来渲染一个组件

问题描述

父组件连接到 Google Cloud FireStore 并使用 setCards 挂钩将所有数据保存到卡片中。

接下来我们将两个子组件导入到我们的父组件中:

<UpdateCard card={card} />
<AddCard totalDoclNumbers={totalDoclNumbers} />

父组件 - DockList

import React, { useState, useEffect } from 'react';
import { db } from '../firebase';
import UpdateCard from './UpdateCard';
import AddCard from './AddCard';

const DocList = () => {
  const [cards, setCards] = useState([]);
  const [beginAfter, setBeginAfter] = useState(0);
  const [totalDoclNumbers, setTotalDoclNumbers] = useState(0);
    
  useEffect(() => {
    const fetchData = async () => {
      const data = await db
        .collection('FlashCards')
        .orderBy('customId')
        .startAfter(beginAfter)
        .get();
      setCards(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
    };
    fetchData();
  }, [beginAfter]);

 
  return (
      <ul className='list'>
        {cards.map((card) => (
          <li key={card.id} className='list__item' data-id={card.id}>
            <UpdateCard card={card} />
          </li>
        ))}
        <AddCard totalDoclNumbers={totalDoclNumbers} />
      </ul>
  );
};

export default DocList;

在 UpdateCard 中,我们使用无序列表列出存储在卡片中的所有数据:

import React, { useState } from 'react';
import { db } from '../firebase';

const UpdateCard = ({ card }) => {
  const [translatedText, setTranslatedText] = useState(card.translatedText);
  const [customId, setCustomId] = useState(card.customId);

  const onUpdate = async () => {
    await db
      .collection('FlashCards')
      .doc(card.id)
      .update({ ...card, customId, originalText, translatedText, imgURL });    
  };

  return (
    <>
      <input
        type='text'
        value={customId}
        onChange={(e) => {
          setCustomId(Number(e.target.value));
        }}
      />
      <textarea
        value={translatedText}
        onChange={(e) => {
          setTranslatedText(e.target.value);
        }}
      />
      <button onClick={onUpdate}>
        Update
      </button>
    </>
  );
};

export default UpdateCard;

最后,在名为AddCard的第二个子组件中,我们有一个按钮,它触发 onAdd 函数将新数据添加到我们的 FireStore 集合中。

import React, { useState } from 'react';
import { db } from '../firebase';

const AddCard = ({ totalDoclNumbers }) => {
  const [newTranslatedText, setNewTranslatedText] = useState([]);
  const nextNumber = totalDoclNumbers + 1;

  const onAdd = async () => {
    await db.collection('FlashCards').add({
      translatedText: newTranslatedText,
      customId: Number(nextNumber),
    });   
  };

  return (
    <ul className='list'>
      <li key={nextNumber}>
        <input
          type='text'
          className='list__input'
          defaultValue={nextNumber}
        />
        <textarea
          onChange={(e) => setNewTranslatedText(e.target.value)}
        />
        <button onClick={onAdd}>
          Add
        </button>
      </li>
    </ul>
  );
};

export default AddCard;

这一切都有效。当您单击第二个子组件AddCard组件内的按钮时,新数据将存储到集合中。

但是为了能够看到新添加的数据,我需要渲染UpdateCard,而这正是我正在努力解决的问题。

如何实现单击 AddCard 组件内的按钮,触发 UpdateCard 组件中的渲染。

标签: reactjsgoogle-cloud-firestorereact-hooks

解决方案


好的,所以首先DocList添加一个回调函数:

const DocList = () => {
  ...
  const [addButtonClickCount, setAddButtonClickCount] = useState(0);
  ...
  return (
      <ul className='list'>
        {cards.map((card) => (
          <li key={card.id} className='list__item' data-id={card.id}>
            <UpdateCard card={card} addButtonClickCount={addButtonClickCount}/>
          </li>
        ))}
        <AddCard totalDoclNumbers={totalDoclNumbers} onAddButtonClick={(card) => {
           setAddButtonClickCount(c => c + 1)
           setCards(cards => [...cards, {...card.data(), id: card.idcard}])
        }} />
      </ul>
  );
};

然后在需要时调用onAddButtonClickAddCard作为道具传递:

const AddCard = ({ totalDoclNumbers, onAddButtonClick }) => {
...
const onAdd = async () => {
    // Somehow you gotta get value of newly created card:
    let card = await db.collection('FlashCards').add({
      translatedText: newTranslatedText,
      customId: Number(nextNumber),
    }); 
    
    // pass the newly created card here so you could use it in `UpdateCard`
    onAddButtonClick(card) // this looks likes where it belongs.
  };

这将导致UpdateCard组件重新渲染,因为它作为道具获得,如果您想在单击添加按钮后addButtonClickCount做某事,您可以使用依赖数组。UpdateCarduseEffect[addButtonClickCount]


推荐阅读