组件挂载时,useEffect 钩子会被调用两次

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

正在开发一个 MERN 应用程序,该应用程序使用 Vite 作为前端并使用 React。我使用 useEffect 挂钩从数据库中获取数据,其中数据列在表中。控制台中没有错误或警告,但当我控制台日志时,刷新页面时似乎 useEffect 挂钩被调用两次。 下面是我的代码:

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

const OperatingSites = () => {
  const [siteData, setSiteData] = useState([
    { location: '', type: '', address: '' } 
  ]);


  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get('http://localhost:5000/operatingSite');
        const fetchData = response.data;
        setSiteData([...fetchData, { location: '', type: '', address: '' }]);
      } catch (error) {
        console.error('Error fetching data:', error);
      }
      
    };

    console.log("UseEffect");
    
    fetchData();
  }, []);


  const handleInputChange = (index, event) => {
    const { name, value } = event.target;
    const newData = [...siteData];
    newData[index][name] = value;
    setSiteData(newData);

    // Automatically add a new row if editing the last row and it's not empty
    if (index === newData.length - 1 && newData[index].location && newData[index].type && newData[index].address) {
      addEmptyRow();
    }
  };

  const addEmptyRow = () => {
    setSiteData([...siteData, { location: '', type: '', address: '' }]);
  };

  const generateRows = () => {
    return siteData.map((site, index) => (
        
      <tr key={index}>
        <td>
          <input
            type="text"
            className="w-full border-none focus:ring-transparent text-center"
            placeholder="Enter location"
            name="location"
            value={site.location}
            onChange={(e) => handleInputChange(index, e)}
          />
        </td>
        <td>
          <select
            className="w-full border-none focus:ring-transparent text-center"
            name="type"
            value={site.type}
            onChange={(e) => handleInputChange(index, e)}
          >
            <option value="">Choose...</option>
            <option value="Primary">Primary</option>
            <option value="Secondary">Secondary</option>
          </select>
        </td>
        <td>
          <input
            type="text"
            className="w-full border-none focus:ring-transparent text-center"
            placeholder="Enter address"
            name="address"
            value={site.address}
            onChange={(e) => handleInputChange(index, e)}
          />
        </td>
      </tr>
    ));
  };

  const handleSubmit = async () => {
    const filteredData = siteData.filter(site => site.location && site.type && site.address);
    try {
      await axios.post('http://localhost:5000/operatingSite', filteredData);
      alert('Data submitted successfully');
    } catch (error) {
      console.error('Error submitting data:', error);
    }
  };


  return (
    <div className="flex">
      
      <div className="w-full pb-20 pt-8 pr-28 pl-28">
        <div className="relative overflow-hidden ">
          <table className="w-full text-center  border border-[#52B14A] ">
            <thead className="bg-[#00bdf6] h-10">
              <tr>
                <th className="py-2">Location</th>
                <th className="py-2">Primary/Secondary</th>
                <th className="py-2">Address</th>
              </tr>
            </thead>
            <tbody className="bg-transparent ">
              {generateRows()}
            </tbody>
          </table>
          <button onClick={handleSubmit} className="mt-4 p-2 bg-blue-500 text-white">
            Submit Changes
          </button>
        </div>
      </div>
    </div>
  );
};

export default OperatingSites;

如您所见,我在钩子内有一个控制台日志来检查它何时被调用:

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

const OperatingSites = () => {
  const [siteData, setSiteData] = useState([
    { location: '', type: '', address: '' } 
  ]);


  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get('http://localhost:5000/operatingSite');
        const fetchData = response.data;
        setSiteData([...fetchData, { location: '', type: '', address: '' }]);
      } catch (error) {
        console.error('Error fetching data:', error);
      }
      
    };

    console.log("UseEffect");
    
    fetchData();
  }, []);

控制台输出将是:

在此输入图片描述

问题是,当我检查console.log时,useEffect被触发两次。因此,代码会两次查询相同的数据,这是应该避免的。这不会影响项目,因为没有错误,但我想知道组件安装时 useEffect 运行两次背后的具体原因。

reactjs react-hooks mern
1个回答
0
投票

很可能您已开启 React StrictMode

请检查您的应用程序是否带有标签

<StrictMode>
。严格模式会渲染组件两次(在开发中而不是在生产中),以便检测代码中的任何问题并向您发出警告(这可能非常有用)。这是预期的行为。

© www.soinside.com 2019 - 2024. All rights reserved.