呈现的第一个容器没有来自 api 在 React 中获取的数据
First container rendered have no data from api fetch in React
我正在获取一个 api,数据正在以结果状态存储。 list state 是一个数组,包含一个带有 id、result 和 responseinput 的对象。 addItem 方法将对象推入 arrayList 并将其推入列表状态。在调用 addItem() 后,在容器内的 return 末尾呈现具有 .map 方法的列表状态,即提交按钮。
只有从 api 获取的 list state array
的第一个索引没有得到存储在结果中的数据,之后的所有索引确实有来自 [=18= 的数据].
我试过 setTimeout 但它不起作用。 .map 方法位于 React 组件的 return 处。我查看了控制台,似乎是第一个渲染,api 正在获取并等待几秒钟,但容器已经添加到网页中,这就是它没有任何数据的原因。想了一整天都找不到解决方案。
export default function CreatePrompt() {
const [responseInput, setResponseInput] = useState("");
const [result, setResult] = useState("");
const [list, setList] = useState([
{
id: 101,
inputPrompt: "What is on your mind?",
value: "You are on my mind.",
}
]);
const onSubmit = (event) => {
event.preventDefault()
const getData = async () => {
const data = {
prompt: responseInput,
temperature: 0.5,
max_tokens: 64,
top_p: 1.0,
frequency_penalty: 0.0,
presence_penalty: 0,
};
try {
const response = await fetch('*********', {
method: 'POST',
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.REACT_APP_USER_KEY}`
},
body: JSON.stringify(data),
})
if (response.ok) {
const jsonResponse = await response.json();
setResult(jsonResponse.choices[0].text)
setResponseInput(responseInput)
}
} catch (error) {
console.log(error);
}
}
getData()
}
const addItem = () => {
if (responseInput !== '') {
const promptObj = {
id: Math.random(),
inputPrompt: responseInput,
value: result,
}
const arrayList = [...list];
arrayList.push(promptObj);
setList(arrayList);
setResponseInput('');
}
}
const deleteItem = (key) => {
const arrayList = [...list]
const updateList = arrayList.filter(item => item.id !== key);
setList(updateList);
}
return (
<div>
<main className="ui container heading-container">
<h1 id="heading">Fun With AI</h1>
<p id="command-description">Hello, my name is GPT-3. Ask me to do something.</p>
<div className="ui form">
<form className="field" onSubmit={onSubmit}>
<label id="prompt-subheading">Enter Prompt</label>
<div className='ui input focus'>
<textarea
type='text'
value={responseInput}
onChange={(e) => setResponseInput(e.target.value)}>
</textarea>
</div>
<button
className="ui button blue right floated"
id="submit-button"
onClick={addItem}
>Submit</button>
</form>
</div>
</main>
<div className="ui container subheading-container">
<h2 id="response-subheading">Responses</h2>
</div>
<div>
{list.map(item => {
return (
<div
className="ui container new-response-container"
key={item.id}
>
<div>
<button
className="ui right floated button grey mini delete-button"
onClick={() => deleteItem(item.id)}
>X
</button>
</div>
<div className="info-container">
<div className="prompt-container">
<h3 className="response-title">Prompt:</h3>
<p id="prompt-input">
{item.inputPrompt}
</p>
</div>
<div className="response-container">
<h3 className="response-title">Response:</h3>
<p id="response-result">{item.value}</p>
</div>
</div>
</div>
)
}).reverse()}
</div>
</div >
)
}
问题
据我所知,您似乎希望用户在 onSubmit
处理程序中使用的 textarea
输入中输入一些值,然后使用 onSubmit
使带有输入数据的 POST 请求和 addItem
使用输入的 responseInput
和解析的响应值更新 list
状态。
当前代码的问题在于 onSubmit
(通过 form
元素的 onSubmit
处理程序) 和 addItem
(通过提交按钮的onClick
处理程序)被同时调用。换句话说,addItem
在 onSubmit
发出 POST 请求并收到响应之前使用未更新的 result
状态值。
解决方案
调用 addItem
或在 onSubmit
回调处理程序中同步处理该逻辑。我还建议使用效用函数生成 GUID,几乎任何东西都比 Math.random()
.
好
请注意,此建议的解决方案完全删除了中间 result
状态 和 addItem
函数,因为响应值完全在 onSubmit
处理程序中处理。
示例:
import { v4 as uuidV4 } from 'uuid';
export default function CreatePrompt() {
const [responseInput, setResponseInput] = useState("");
const [list, setList] = useState([
{
id: uuidV4(),
inputPrompt: "What is on your mind?",
value: "You are on my mind.",
}
]);
const onSubmit = (event) => {
event.preventDefault()
const getData = async () => {
const data = {
prompt: responseInput,
temperature: 0.5,
max_tokens: 64,
top_p: 1.0,
frequency_penalty: 0.0,
presence_penalty: 0,
};
try {
const response = await fetch('*********', {
method: 'POST',
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.REACT_APP_USER_KEY}`
},
body: JSON.stringify(data),
});
if (response.ok) {
const jsonResponse = await response.json();
const promptObj = {
id: uuidV4(),
inputPrompt: responseInput, // save current prompt input
value: jsonResponse.choices[0].text, // save resolved response value
}
setList(list => [...list, promptObj); // enqueue list state update
setResponseInput(''); // clear out prompt value
}
} catch (error) {
console.log(error);
}
};
if (responseInput) {
getData();
}
};
删除提交按钮的 onClick
处理程序。请注意,即使 type="submit"
是默认的 type
属性值,最好还是通过指定 type="submit"
来明确说明,这样就 明显地 清楚了按钮提交表单的任何未来读者。
<main className="ui container heading-container">
<h1 id="heading">Fun With AI</h1>
<p id="command-description">Hello, my name is GPT-3. Ask me to do something.</p>
<div className="ui form">
<form className="field" onSubmit={onSubmit}>
<label id="prompt-subheading">Enter Prompt</label>
<div className='ui input focus'>
<textarea
type='text'
value={responseInput}
onChange={(e) => setResponseInput(e.target.value)}
/>
</div>
<button
className="ui button blue right floated"
id="submit-button"
type="submit"
>
Submit
</button>
</form>
</div>
</main>
我正在获取一个 api,数据正在以结果状态存储。 list state 是一个数组,包含一个带有 id、result 和 responseinput 的对象。 addItem 方法将对象推入 arrayList 并将其推入列表状态。在调用 addItem() 后,在容器内的 return 末尾呈现具有 .map 方法的列表状态,即提交按钮。
只有从 api 获取的 list state array
的第一个索引没有得到存储在结果中的数据,之后的所有索引确实有来自 [=18= 的数据].
我试过 setTimeout 但它不起作用。 .map 方法位于 React 组件的 return 处。我查看了控制台,似乎是第一个渲染,api 正在获取并等待几秒钟,但容器已经添加到网页中,这就是它没有任何数据的原因。想了一整天都找不到解决方案。
export default function CreatePrompt() {
const [responseInput, setResponseInput] = useState("");
const [result, setResult] = useState("");
const [list, setList] = useState([
{
id: 101,
inputPrompt: "What is on your mind?",
value: "You are on my mind.",
}
]);
const onSubmit = (event) => {
event.preventDefault()
const getData = async () => {
const data = {
prompt: responseInput,
temperature: 0.5,
max_tokens: 64,
top_p: 1.0,
frequency_penalty: 0.0,
presence_penalty: 0,
};
try {
const response = await fetch('*********', {
method: 'POST',
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.REACT_APP_USER_KEY}`
},
body: JSON.stringify(data),
})
if (response.ok) {
const jsonResponse = await response.json();
setResult(jsonResponse.choices[0].text)
setResponseInput(responseInput)
}
} catch (error) {
console.log(error);
}
}
getData()
}
const addItem = () => {
if (responseInput !== '') {
const promptObj = {
id: Math.random(),
inputPrompt: responseInput,
value: result,
}
const arrayList = [...list];
arrayList.push(promptObj);
setList(arrayList);
setResponseInput('');
}
}
const deleteItem = (key) => {
const arrayList = [...list]
const updateList = arrayList.filter(item => item.id !== key);
setList(updateList);
}
return (
<div>
<main className="ui container heading-container">
<h1 id="heading">Fun With AI</h1>
<p id="command-description">Hello, my name is GPT-3. Ask me to do something.</p>
<div className="ui form">
<form className="field" onSubmit={onSubmit}>
<label id="prompt-subheading">Enter Prompt</label>
<div className='ui input focus'>
<textarea
type='text'
value={responseInput}
onChange={(e) => setResponseInput(e.target.value)}>
</textarea>
</div>
<button
className="ui button blue right floated"
id="submit-button"
onClick={addItem}
>Submit</button>
</form>
</div>
</main>
<div className="ui container subheading-container">
<h2 id="response-subheading">Responses</h2>
</div>
<div>
{list.map(item => {
return (
<div
className="ui container new-response-container"
key={item.id}
>
<div>
<button
className="ui right floated button grey mini delete-button"
onClick={() => deleteItem(item.id)}
>X
</button>
</div>
<div className="info-container">
<div className="prompt-container">
<h3 className="response-title">Prompt:</h3>
<p id="prompt-input">
{item.inputPrompt}
</p>
</div>
<div className="response-container">
<h3 className="response-title">Response:</h3>
<p id="response-result">{item.value}</p>
</div>
</div>
</div>
)
}).reverse()}
</div>
</div >
)
}
问题
据我所知,您似乎希望用户在 onSubmit
处理程序中使用的 textarea
输入中输入一些值,然后使用 onSubmit
使带有输入数据的 POST 请求和 addItem
使用输入的 responseInput
和解析的响应值更新 list
状态。
当前代码的问题在于 onSubmit
(通过 form
元素的 onSubmit
处理程序) 和 addItem
(通过提交按钮的onClick
处理程序)被同时调用。换句话说,addItem
在 onSubmit
发出 POST 请求并收到响应之前使用未更新的 result
状态值。
解决方案
调用 addItem
或在 onSubmit
回调处理程序中同步处理该逻辑。我还建议使用效用函数生成 GUID,几乎任何东西都比 Math.random()
.
请注意,此建议的解决方案完全删除了中间 result
状态 和 addItem
函数,因为响应值完全在 onSubmit
处理程序中处理。
示例:
import { v4 as uuidV4 } from 'uuid';
export default function CreatePrompt() {
const [responseInput, setResponseInput] = useState("");
const [list, setList] = useState([
{
id: uuidV4(),
inputPrompt: "What is on your mind?",
value: "You are on my mind.",
}
]);
const onSubmit = (event) => {
event.preventDefault()
const getData = async () => {
const data = {
prompt: responseInput,
temperature: 0.5,
max_tokens: 64,
top_p: 1.0,
frequency_penalty: 0.0,
presence_penalty: 0,
};
try {
const response = await fetch('*********', {
method: 'POST',
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.REACT_APP_USER_KEY}`
},
body: JSON.stringify(data),
});
if (response.ok) {
const jsonResponse = await response.json();
const promptObj = {
id: uuidV4(),
inputPrompt: responseInput, // save current prompt input
value: jsonResponse.choices[0].text, // save resolved response value
}
setList(list => [...list, promptObj); // enqueue list state update
setResponseInput(''); // clear out prompt value
}
} catch (error) {
console.log(error);
}
};
if (responseInput) {
getData();
}
};
删除提交按钮的 onClick
处理程序。请注意,即使 type="submit"
是默认的 type
属性值,最好还是通过指定 type="submit"
来明确说明,这样就 明显地 清楚了按钮提交表单的任何未来读者。
<main className="ui container heading-container">
<h1 id="heading">Fun With AI</h1>
<p id="command-description">Hello, my name is GPT-3. Ask me to do something.</p>
<div className="ui form">
<form className="field" onSubmit={onSubmit}>
<label id="prompt-subheading">Enter Prompt</label>
<div className='ui input focus'>
<textarea
type='text'
value={responseInput}
onChange={(e) => setResponseInput(e.target.value)}
/>
</div>
<button
className="ui button blue right floated"
id="submit-button"
type="submit"
>
Submit
</button>
</form>
</div>
</main>