socket.on 在地图 React 中发送 socket.emit() 时状态未更改
socket.on State Not Changing while sending socket.emit() in a map React
我正在使用 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')
时,我可以看到创建的 运行 的值。但是,只有第二个 运行(如果 project.tests
的长度为 2),只有最后一个 运行 被添加到状态。
我在这里错过了什么?请帮帮我!提前致谢!
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>
);
}
我正在使用 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')
时,我可以看到创建的 运行 的值。但是,只有第二个 运行(如果 project.tests
的长度为 2),只有最后一个 运行 被添加到状态。
我在这里错过了什么?请帮帮我!提前致谢!
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>
);
}