需要使用相同组件重新加载路线更改数据 - React TSX

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

现在,我遇到了麻烦,因为我从 Firebase Firestore 收到的数据能够在两条路由上加载,但是,只有在路由链接上单击两次时才会加载,否则旧数据在路由更改之间仍然存在。我的目标是在路线更改时重置数据。

这是我从 Firestore 收到并显示的零件编号网格代码:

var arrSnap:QueryDocumentSnapshot[] = [];

async function populateGrid(){
const currentRoute = useLocation()
var program = currentRoute.replace('/parts-list/', '');


var querySnapshot;
if (program === 'First'){
     querySnapshot = await getDocs(collection(db, "Programs", "----", program, "-----", "Parts"));

}else if(program === 'Second'){
     querySnapshot = await getDocs(collection(db, "Programs", "----", program, "-----", "Parts"));

}else{

}

const _arrSnap:QueryDocumentSnapshot[] = [];

querySnapshot.forEach((doc) => {
    _arrSnap.push(doc);
  });
  console.log(_arrSnap[0].get("PN"));
  arrSnap = [..._arrSnap];
  
 }




export default function CardGrid(){
   populateGrid();




return (
    <>
    <div className="tlCont">
        <div className="gridCont">
           {[...arrSnap].map((e, i) => {
return (

<div className="gridItm" key={arrSnap[i].get("PN")}>
    <Card > 
Part Number: {arrSnap[i].get("PN")}
<br></br>
Description: {arrSnap[i].get("DESCRIPTION")}
<br></br>
Form Tool: {arrSnap[i].get("FORM TOOL")}
<br></br>
Trim Tool: {arrSnap[i].get("TRIM TOOL")}
</Card>

    </div>
)


           })}
        </div>

    </div>
    </>
    )
}

我怀疑这与在加载的组件内调用函数“populateGrid()”有关。

reactjs typescript firebase google-cloud-firestore react-hooks
1个回答
0
投票

问题

  • populateGrid
    被称为无意的副作用
  • populateGrid
    改变全局
    arrSnap
    数组引用。这不会触发
    CardGrid
    组件重新渲染,因此需要以其他方式触发组件来重新渲染,即第二次单击路线链接。随后的渲染会公开变异的“arrSnap”数组值。

解决方案

  • populateGrid
    应该被称为 ann 有意的副作用,例如使用
    useEffect
    钩子
  • 将获取的 Firebase 文档数据存储到本地 React 状态中,以便在更新时触发组件重新渲染。

示例:

export default function CardGrid() {
  const { pathname } = useLocation();

  const [arrSnap, setArrSnap] = React.useState<QueryDocumentSnapshot[]>([]);

  React.useEffect(() => {
    const populateGrid = async () => {
      const program = /* use pathname to compute program */;
    
      let doc;

      switch(program) {
        case "First":
          doc = collection(db, "Programs", "----", program, "-----", "Parts");
          break;

        case "Second":
          doc = collection(db, "Programs", "----", program, "-----", "Parts");
          break;

        default:
      }

      try {
        const querySnapshot = await getDocs(doc);
        const arrSnap: QueryDocumentSnapshot[] = [];
    
        querySnapshot.forEach((doc) => {
          arrSnap.push(doc);
        });

        setArrSnap(arrSnap);
      } catch(error) {
        // handle/ignore
      }
    };

    populateGrid();
  }, [pathname]);
   
  return (
    <div className="tlCont">
      <div className="gridCont">
        {arrSnap.map((item) => (
          <div className="gridItm" key={item.get("PN")}>
            <Card> 
              Part Number: {item.get("PN")}
              <br></br>
              Description: {item.get("DESCRIPTION")}
              <br></br>
              Form Tool: {item.get("FORM TOOL")}
              <br></br>
              Trim Tool: {item.get("TRIM TOOL")}
            </Card>
          </div>
        ))}
      </div>
    </div>
  );
}

将逻辑抽象到自定义挂钩中可能是值得的。

基本示例:

const usePopulateGrid = <T extends unknown>() => {
  const { pathname } = useLocation();

  const [data, setData] = React.useState<T[]>([]);

  React.useEffect(() => {
    const populateGrid = async () => {
      const program = /* use pathname to compute program */;
    
      let doc;

      switch(program) {
        case "First":
          doc = collection(db, "Programs", "----", program, "-----", "Parts");
          break;

        case "Second":
          doc = collection(db, "Programs", "----", program, "-----", "Parts");
          break;

        default:
      }

      try {
        const querySnapshot = await getDocs(doc);
        const data: T[] = [];
    
        querySnapshot.forEach((doc) => {
          data.push({
            ...doc.data(),
            id: doc.id
          } as T);
        });

        setData(data);
      } catch(error) {
        // handle/ignore
      }
    };

    populateGrid();
  }, [pathname]);

  return data;
};
interface GridData {
  id: string;
  partNumber: string;
  description: string;
  formTool: string;
  trimTool: string;
}

export default function CardGrid() {
  const gridData = usePopulateGrid<GridData>();
   
  return (
    <div className="tlCont">
      <div className="gridCont">
        {gridData.map((item) => (
          <div className="gridItm" key={item.id}>
            <Card> 
              Part Number: {item.partNumber}
              <br></br>
              Description: {item.description}
              <br></br>
              Form Tool: {item.formTool}
              <br></br>
              Trim Tool: {item.trimTool}
            </Card>
          </div>
        ))}
      </div>
    </div>
  );
}
© www.soinside.com 2019 - 2024. All rights reserved.