0

我正在socket.io与一个项目一起使用react。这是我的组件

import axios from 'axios';
import React, { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { io } from 'socket.io-client';
import Button from '../../components/Button';
import { IProject } from '../../interfaces/projects';
import { IRun } from '../../interfaces/runs';

const socket = io(process.env.REACT_APP_SERVER_URL);

export default function RunAll() {
    const { search } = useLocation();

    // API State
    const [project, setProject] = useState<IProject | undefined>(undefined);
    const [runs, setRuns] = useState<IRun[]>([]);

    // Query Params
    const queryParams = new URLSearchParams(search);
    const projectId = queryParams.get('projectId')!;

    // Get Project
    useEffect(() => {
        (async () => {
            const { data: project } = await axios.get(`${process.env.REACT_APP_SERVER_URL}/api/projects/${projectId}`);

            setProject(project.data);
        })();
    }, [projectId]);

    // Clear socket
    useEffect(() => () => {
        socket.close();
    });

    const runAllTests = async () => {
        project?.tests.forEach((test) => {
            console.log(test);
            socket.emit('create run', { projectId, testId: test.id, url: process.env.REACT_APP_SERVER_URL });
        });

        socket.on('created run', (run: IRun) => {
            console.log(run);
            setRuns([...runs, run]);
        });
    };
    console.log(runs);

    const renderHeader = () => (
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', alignItems: 'center' }} className='mb-3'>
            <h1 className='heading-primary mt-auto mb-auto'>Run Overview</h1>

            <Button onClick={runAllTests}>Run All Tests</Button>
        </div>
    );

    return (
        <main>
            {renderHeader()}
            {runs?.map((run) => (
                <div>{run.id}</div>
            ))}
        </main>
    );
}

单击并runAllTests()调用该按钮时,我可以console.log(test)在控制台中看到 ,并且我的服务器日志也显示它已收到socket.emit('create run'). 当服务器响应时socket.on('created run'),我可以看到创建运行的值。但是,只有第 2 次运行(如果长度为project.tests2),只有最后一次运行被添加到状态中。

我在这里想念什么?请帮帮我!提前致谢!

4

1 回答 1

1
    socket.on('created run', (run: IRun) => { console.log(run); setRuns([...runs, run]); }); 

在 useEffect 中使用此代码并确保它只运行一次。以下应该对你有用。

import axios from 'axios';
import React, { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { io } from 'socket.io-client';
import Button from '../../components/Button';
import { IProject } from '../../interfaces/projects';
import { IRun } from '../../interfaces/runs';

const socket = io(process.env.REACT_APP_SERVER_URL);

export default function RunAll() {
    const { search } = useLocation();

    // API State
    const [project, setProject] = useState<IProject | undefined>(undefined);
    const [runs, setRuns] = useState<IRun[]>([]);

    // Query Params
    const queryParams = new URLSearchParams(search);
    const projectId = queryParams.get('projectId')!;

    // Get Project
    useEffect(() => {
        (async () => {
            const { data: project } = await axios.get(`${process.env.REACT_APP_SERVER_URL}/api/projects/${projectId}`);

            setProject(project.data);
        })();
    }, [projectId]);

    // Clear socket
    useEffect(() => () => {
        socket.on('created run', (run: IRun) => {
            console.log(run);
            setRuns([...runs, run]);
        });
        
        return function cleanup () {
           socket.close();
        }

    },[]);

    const runAllTests = async () => {
        project?.tests.forEach((test) => {
            console.log(test);
            socket.emit('create run', { projectId, testId: test.id, url: process.env.REACT_APP_SERVER_URL });
        });

        
    };
    console.log(runs);

    const renderHeader = () => (
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', alignItems: 'center' }} className='mb-3'>
            <h1 className='heading-primary mt-auto mb-auto'>Run Overview</h1>

            <Button onClick={runAllTests}>Run All Tests</Button>
        </div>
    );

    return (
        <main>
            {renderHeader()}
            {runs?.map((run) => (
                <div>{run.id}</div>
            ))}
        </main>
    );
}
于 2021-07-30T12:32:29.593 回答