3

Ran into a problem with hooks today. I know there is a similar post, and I read the rules of using hooks. Right now when I post my form, it gives me that error. And I know that's because my hook is INSIDE an if statement. But how can I get it out? I don't know how else to use this hook if it's not in a function or a statement. Any advice would be greatly appreciated. Here is the code:

import React, { FunctionComponent, useState, useEffect } from 'react';
import usePost from '../hooks/usepost'
import Article from './article';

interface ArticlePosted {
    title: string,
    body: string,
    author: string
}
const Post: FunctionComponent = () => {

    const [details, detailsReady] = useState({})
    const postArticle = (e) => {
        e.preventDefault()
        const postDetails = {
            title: e.target.title.value,
            body: e.target.body.value,
            author: e.target.author.value
        }
        detailsReady(postDetails)
    }

    if (Object.keys(details).length !== 0) {
        console.log(details)
        usePost('http://localhost:4000/kb/add', details)
    }
    return (
        <div>
            <form onSubmit={postArticle}>
                <p>
                    Title <input type='text' name='title' />
                </p>
                <p>
                    Body <textarea name='body' rows={4} />
                </p>
                <p>
                    Author <input type='text' name='author' />
                </p>
                <button type='submit'>Submit Article</button>

            </form>
        </div>
    );
};

export default Post;

Custom Hook:

import React, { useState, useEffect } from 'react';
import axios from 'axios';

const usePost = (url, postDetails) => {
    //set empty object as data
    console.log(url, "DFLSKDJFSDLKFJDLKJFDLFJ")

    console.log(postDetails)
    useEffect(() => {
        console.log('usePost running')
        axios.post(url, postDetails)
            .then(res => {
                console.log(res)
                return
            })
    }
        , [postDetails]);

};

export default usePost
lakerskill
  • 1,019
  • 1
  • 11
  • 24

1 Answers1

3

You can move the if-statement logic into the usePost hook.

const usePost = (url, postDetails) => {
    useEffect(() => {
        if (Object.keys(postDetails).length === 0){
            return console.log('Not posting'); // Don't post anything if no details
        }
        // Otherwise, post away
        console.log('usePost running')
        axios.post(url, postDetails)
            .then(res => {
                console.log(res)
                return
            })
    }
        , [postDetails]);

};
Noah May
  • 1,049
  • 8
  • 18
  • then how would it know hen to send the data from the post component – lakerskill Aug 16 '19 at 04:12
  • I moved the if statement into the `useEffect`. If the `postDetails` contains anything, the effect hook will post to the url, otherwise it will return early and stop running the rest of the function. – Noah May Aug 16 '19 at 04:17
  • Quite simply, you're solution was awesome. Thank you kindly! – lakerskill Aug 16 '19 at 04:30
  • Just cause something works doesn't mean it's good code. Why are you even using useEffect? @lakerskill – FabricioG Aug 12 '20 at 21:47
  • @FabricioG I assume lakerskill doesn't want to repost the details every rerender if they stay static. This could be done with a manual `if (postDetails === prevPostDetails)` but this is easier. – Noah May Aug 12 '20 at 22:48