I have the below functional component in a simple MERN application. My problem is the output
state is reset to ["Let's run a test..."]
when the API call returns, so I always only get an array of that and the last output, instead of an array of all outputs.
output
state looks like: ["Let's run a test..."]
on refresh the page, ["Running tests...]
on testRunner
click, and ["Let's run a test...", "test result"]
on testRunner
response. I'm expecting ["Running tests...", "test result 1", "test result 2", ...]
on testRunner
response. Is useEffect
having some effect I'm not aware of? How should I be doing this?
import React, { useState, useEffect } from 'react';
import apis from '../api/index';
import Header from './Header';
import Output from './Output';
function App() {
const [output, setOutput] = useState([]);
const testRunner = async () => {
setOutput(["Running tests..."]);
for (const item of selectedItemTypes) {
const payload = {
"itemPrefix": item,
"testFunction": selectedTestFunctions
};
await apis.testRunner(payload).then(res => {
setOutput([...output, `${item}: ${res.data.result}`]);
});
}
}
useEffect(() => {
async function initialize() {
setOutput(["Let's run a test..."]);
}
initialize();
}, []);
return (
<div className="App">
<Header
testRunner={testRunner}
/>
<Container>
<ChildContainer>
<TitleDiv>Select Test Function(s)</TitleDiv>
<TestPicker />
</ChildContainer>
<ChildContainer>
<TitleDiv>Select Item Type(s)</TitleDiv>
<ItemTypePicker />
</ChildContainer>
<ChildContainer>
<TitleDiv>Output</TitleDiv>
<Output
output={output}
/>
</ChildContainer>
</Container>
</div>
);
}
export default App;
You need to pass the old output value to setOutput in order to get the result you want. So in your testRunner function you'll do something like this.
await apis.testRunner(payload).then(res => {
setOutput((output) => [...output, `${item}: ${res.data.result}`]);
});