【问题标题】:Axios + React (Next.js), post request loses track of the context / stateAxios + React (Next.js),发布请求失去了对上下文/状态的跟踪
【发布时间】:2022-09-14 19:27:22
【问题描述】:

几个小时以来一直在挠头,这个错误对我没有任何意义。

this 解决的问题类似,react 上下文和状态在请求完成后丢失。唯一的问题是我所有的功能都已经绑定了。

每次单击按钮时,下面的代码应返回一个图像 url 并将其添加到 \"image\" 数组状态。 不行的是,“image”数组状态的内容在 axios promise 中被神奇地遗忘了,这意味着之前的所有图像都丢失了,只有请求返回的图像才会以状态结束。

我以前从来没有发生过这样的事情,感觉我一定错过了我犯的一些非常愚蠢的错误。有人知道这里可能发生什么吗?

谢谢,

// Added
const RANDOM_PROMPTS = [
    \'a whale flying in the sky\',
    \'a skeleton dancing\',
    \'a sunflower growing in a field\'
]

export default function Home() {

    const [prompt, setPrompt] = useState(\'\')
    const [images, setImages] = useState([])

    // Added
    useEffect(() => {
        randomPrompt()
    }, []) 

    const handleSubmit = event => {
        event.preventDefault()
        event.stopPropagation()

        axios.post(\'http://localhost:3000/v1/generate\', {prompt})
        .then(res => {
            res.data && add(res.data.url)
        })
    }

    const add = (url) => {
        // images state is always [] here
        console.log(images)
        setImages([...images, url])
    }
    
    // Added
    const randomPrompt = () => {
        const prompt = RANDOM_PROMPTS.shift()
        
        setPrompt(`a painting of ${prompt}, by Paul Delvaux`)
    }

    return (
        <div>
            <form onSubmit={handleSubmit}>
                <input type=\"text\" value={prompt} onChange={event => setPrompt(event.target.value)}/>
                <button type=\"submit\">Draw</button>
            </form>
        </div>
    )
}
  • 您是否尝试在使用 useEffect() 钩子执行的不同函数中发起 Axios 请求? (我的意思是handleSubmit 可以更改一个变量,该变量将成为useEffect 的依赖项)
  • 我确实有一个 useEffect 钩子,但据我了解,它没有连接到或以任何方式启动 axios 请求。也就是说,当我删除它时,它开始按预期工作。 useEffect 用于随机化安装时的提示,我已经编辑了问题并将其添加到代码中。如果您了解这如何破坏 axios 请求,我很想听听您的想法。
  • 非常感谢你帮我修复它。另外,我现在应该担心 useEffect 钩子会从应用程序的完全不同部分破坏 axios 吗?
  • 我认为 KALrious 指出了一个很好的观点。我编辑了我的答案,将 useEffect 与异步函数调用包括在内。他的回答也应该解决这个问题

标签: reactjs next.js axios


【解决方案1】:

您是否尝试使您的函数处理提交异步函数?

 const handleSubmit = async (event) => {
        event.preventDefault()
        event.stopPropagation()

        const {data} = await axios.post('http://localhost:3000/v1/generate', 
        {prompt},{
         validateStatus: (status) => status === 201,
        })
        if(!!data && !!data.url) {
          add(data.url)
        }
    }

Je rajouterais que tu peux 修饰符 ta fonction 添加 comme suit:

const add = (url) => {
        console.log(images)
        setImages((prevState) => [...prevState, url])
    }

我的观点是在 .then 你可能会失去你的反应状态的上下文。

【讨论】:

  • Async + await handleSumbit 没有区别,但“setImages((prevState) => [...prevState, url])” 有效!哇,我不知道我可以像在 setState 挂钩中那样使用 prevState,而且我多年来一直在做出反应,哈哈。你知道的越多。谢谢你。我仍然很困惑上下文是如何丢失的,但很高兴你找到了解决方案。
  • 请帮助你一点;)
【解决方案2】:

随机提示不​​应该对您在不同的 useEffect() 依赖项上发出的 Axios 请求产生任何影响。请尝试下面的代码,我尝试按照我在评论中的建议进行操作。

const RANDOM_PROMPTS = [
    'a whale flying in the sky',
    'a skeleton dancing',
    'a sunflower growing in a field'
]

export default function Home() {

    const [prompt, setPrompt] = useState('')
    const [images, setImages] = useState([])
    const [initiateRequest, setInitiateRequest] = useState(false)

    // Added
    useEffect(() => {
        randomPrompt()
    }, []) 

async function fetchData() {
    let response = axios.post('http://localhost:3000/v1/generate', {prompt})
        .then(res => {
            res.data && add(res.data.url)
        })
  }
    useEffect(() => {
        fetchData()
    }, [initiateRequest]) 

    const handleSubmit = event => {
        event.preventDefault()
        event.stopPropagation()
        setInitiateRequest(true)
    }

    const add = (url) => {
        // images state is always [] here
        console.log(images)
        setImages([...images, url])
    }
    
    // Added
    const randomPrompt = () => {
        const prompt = RANDOM_PROMPTS.shift()
        
        setPrompt(`a painting of ${prompt}, by Paul Delvaux`)
    }

    return (
        <div>
            <form onSubmit={handleSubmit}>
                <input type="text" value={prompt} onChange={event => setPrompt(event.target.value)}/>
                <button type="submit">Draw</button>
            </form>
        </div>
    )
}

【讨论】:

  • 太奇怪了,异步没有任何区别。虽然这应该是我尝试的第一件事,但我几乎从不使用 .then()。 KALrious 的回答告诉我,我可以在设置状态时在变压器中使用 prevState,我不知道这是可能的。这似乎是最干净的解决方案。虽然我仍然有点困惑上下文是如何丢失的,但很高兴有一个巧妙的解决方案。感谢您的帮助,Ozgur Sar
猜你喜欢
  • 2021-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-30
  • 2020-04-05
  • 1970-01-01
  • 2021-11-17
  • 2019-02-25
相关资源
最近更新 更多