Home > Software engineering >  Axios React (Next.js), post request loses track of the context / state
Axios React (Next.js), post request loses track of the context / state

Time:09-14

Been scratching my head for hours, this bug doesn't make any sense to me.

Similarly to this solved problem, the react context and state is lost after the request is complete. The only problem is that all my functions are already bound.

The code below should return an image url and add it to the "image" array state every time the button is clicked. What's not working is that the contents of the "image" array state is magically forgotten inside the axios promise, meaning that all previous images are lost, and only the image returned by the request will end up in the state.

I never had something like this happen before, feel like i must be missing some incredibly stupid mistake i've made. Anyone have any ideas what might be going on here?

Thank you,

// 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>
    )
}

CodePudding user response:

Random Prompts should not have any effect on the Axios request you are making on a different useEffect() dependency. Please try my code below which I tried to do what I suggested in my comment.

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>
    )
}

CodePudding user response:

Did you try to make youre function handleSubmit async function ?

 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 modifier ta fonction add comme suit:

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

My opinion is during the .then you may lose the contexte of youre react state.

  • Related