Я пытаюсь создать массив URL-адресов, массив называется «предложения». До сих пор я видел, что вы должны использовать useState, если хотите поместить ответ API в массив. Это то, что я пробовал до сих пор.
const [sentences, setSentences] = useState([]);
const getOpenAIResponse = () => {
for (var i = 0; i < 6; i++) {
openai.createImage({
prompt: prompts[i],
n: 1,
size: "256x256",
}).then((response) => {
setSentences(response.data.data[0].url)
console.info(sentences)
})
}
};
Проблема заключается в том, что предложения просто обновляются со следующим сгенерированным ответом URL. Использование setSentences.push(...) не работает. Есть что-нибудь, что бы вы порекомендовали?
Похоже, я не учел, что при запуске getOpenAIResponse вы вызываете openai.createImage 6 раз, и при каждом запуске вы получаете URL, который нужно добавить в sentences. Вот некоторый обновленный код, который должен работать для вас:
const getOpenAIResponse = () => {
imagePromises = [];
// Collect all image promises in an array
for (var i = 0; i < 6; i++) {
imagePromises.push(
openai.createImage({
prompt: prompts[i],
n: 1,
size: "256x256",
})
);
}
// Do something once all promises resolve
Promise.all(imagePromises)
.then((responses) => {
setSentences([
// Keep current list of sentences
...sentences,
// Add new sentences to old list of sentences
...responses.map(response => response.data.data[0].url),
]);
});
};
Там, где у вас есть setSentences(response.data.data[0].url), это заменит ваш существующий МАССИВ предложений только одним конкретным предложением, возвращаемым openai.createImage. Что вы хотите, так это взять возвращенный URL-адрес, добавить его в свой массив sentences, а затем обновить состояние.
Для этого замените строку setSentences на setSentences(sentences.concat(response.data.data[0].url)).
Я не понимаю, как вы использовали .push раньше, но .push не «возвращает» обновленный массив, а .concat делает!
Вы можете увидеть это в консоли разработчика Chrome с помощью этих двух тестов:
// This returns 4 which is the size of the array!
[1,2,3].push(4);
// These return [1,2,3,4] which is the new array, with the added new element at the end
[1,2,3].concat(4);
[1,2,3].concat([4]);
@CherryDT не нужен, если вы добавляете только 1 элемент в массив sentences, вам не нужно оборачивать response.data.data[0].url в массив
Он будет вести себя неожиданно, если этот элемент сам по себе является массивом, поэтому лучше изучить его последовательно с самого начала, чтобы избежать будущих сюрпризов. В качестве альтернативы я бы рекомендовал (возможно, более чистый) синтаксис [...sentences, response.data.data[0].url].
@CherryDT Вы уверены, что он будет вести себя неожиданно? Если я это сделаю [1,2].concat([3]), я не увижу новый массив как [1,2,[3]], я увижу [1,2,3]
Вот именно это и неожиданно. Если вы узнаете, что «a.concat(x) будет добавлять x к массиву», вы будете удивлены случаем, который вы только что показали, где x было бы [3], а не 3, но в массив было добавлено 3. Я поклонник четко определенных универсальных инструментов, чтобы узнать, где вам не придется помнить о пограничных случаях позже (примером подобной проблемы может быть new Array(...), где передача одного аргумента, который оказывается числом, приведет к к совершенно другому поведению, чем во всех других случаях - и это даже причина, по которой он устарел). Мои два цента.
Ааа, теперь я понимаю, что вы имеете в виду @CherryDT - я думаю, я привык к этому, так что это больше не «неожиданно», но, как вы упомянули, может быть неплохо сделать код очень явным, чтобы вы знали, как иметь дело с x vs [x] имеет разное поведение. Однако в этом конкретном случае, я думаю, ситуация достаточно ясна в обоих решениях, что новый URL-адрес будет добавлен в массив - если .url начинает быть массивом URL-адресов, его следует переименовать .urls, чтобы указать, что
Спасибо. Почему-то сохраняется та же проблема. Предложение [0] изменяется 6 раз, и как только я снова нажимаю кнопку, которая активирует ответ API, я получаю предложение [1], которое также регенерируется 6 раз. Кажется, он не дает мне массив URL-адресов, как я хочу.
@ati Хорошо, когда вы нажимаете кнопку, это вызывает getOpenAIResponse, верно? Похоже, проблема, которую мы не решили, заключается в том, что вы запускаете openai.createImage 6 раз для каждого нажатия кнопки, и каждый раз вы ожидаете, что 6 новых URL-адресов вернутся и будут добавлены в sentences, это правильно?
@ati взгляните на обновленный ответ, я учел тот факт, что у вас есть несколько обещаний, которые необходимо разрешить, прежде чем добавлять полученные предложения в состояние массива!
Хм, но теперь я считаю, что вам действительно нужен массив в вашем последнем ответе :) Верно? Потому что setSentences должен иметь только один аргумент, новое значение, а не несколько. Так и должно быть setSentences([...sentences, ...newStuff])
Спасибо, я только что попробовал, и я получаю букву h для предложений [0], а затем 6 ошибок изображения. @BlunderingPhilosopher @cherryDT
@CherryDT выглядит так, как будто вы профессиональный QAer 😅 Клянусь, я добавил это (не смотрите на историю редактирования этого ответа 🙏) - также Ати - теперь это должно работать - извините за небольшую опечатку
@ati просто чтобы вы знали, я просто предполагаю, что response.data.data[0].url - это правильный способ получить URL-адрес изображения из вашего ответа API - вы можете трижды проверить его точность: D
Вы можете использовать оператор распространения, чтобы добавить новый URL-адрес в массив.
setSentences([...sentences, response.data.data[0].url])
Вы также можете использовать метод concat, чтобы добавить новый URL-адрес в массив.
setSentences(sentences.concat(response.data.data[0].url))
Спасибо, но почему-то такая же проблема. предложения [0] меняются 6 раз, и как только я снова нажимаю кнопку, которая активирует ответ API, я получаю предложения [1], которые также регенерируются 6 раз. Кажется, он не дает мне массив URL-адресов, как я хочу.
Разве аргумент не должен быть заключен в массив?