Реагировать на крючок useState - я хочу отображать определенный компонент, только когда нажимаю кнопку отправки, а не когда onChange

Я новичок, чтобы реагировать.

Теперь пытаюсь создать форму с реагирующими хуками, и я хочу отображать облачный компонент только при нажатии кнопки отправки. Но он отображал каждый вызов onChange.

Я знаю, что повторная визуализация onChange также вызывает крючок useState.

Но понятия не имею, как отображать только при нажатии кнопки отправки.

Моя конечная цель - написать имя и нажать Enter, если значение не содержится в API, setShake сделать встряхивание True, а если True, поместить класс Shake-Cloud в Cloud.js.

РЕАКТИРОВАТЬ СЛИШКОМ СЛОЖНО :(

Спасибо за помощь :)

App.js

import React, { useState, useEffect } from "react";
import "./App.css";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faSearch } from "@fortawesome/free-solid-svg-icons";
import "./search.css";
import PageTitle from "./component/PageTitle";
import Cloud from "./component/Cloud";
import Loading from "./component/Loading";

//https://api.color.pizza/v1/
//data.colors[0].name

const App = () => {
    const [isLoading, setIsLoading] = useState(false);
    const [colorNames, setColorNames] = useState("");
    const [search, setSearch] = useState("");
    const [query, setQuery] = useState("");
    const [cloudHex, setCloudHex] = useState("ivory");
    const [shake, setShake] = useState(false);

    useEffect(() => {
        getColorLists();
    }, []);

    const getColorLists = async () => {
        const res = await fetch(`https://api.color.pizza/v1/`);
        const data = await res.json();
        await setColorNames(data);
        setIsLoading(true);
    };

    const isColor = () => {
        let makeUpper =
            query.search(/\s/) == -1
                ? query.charAt(0).toUpperCase() + query.slice(1)
                : query
                      .split(" ")
                      .map((i) => i.charAt(0).toUpperCase() + i.slice(1))
                      .join(" ");

        for (let i = 0; i < colorNames.colors.length; i++) {
            if (colorNames.colors[i].name == makeUpper) {
                setCloudHex(colorNames.colors[i].hex);
                return;
            } else if (i == colorNames.colors.length - 1) {
                return makeShake();
            }
        }
    };

    const updateSearch = (e) => {
        setSearch(e.target.value);
    };
    const getSearch = (e) => {
        e.preventDefault();
        setQuery(search);
        isColor();
    };

    const makeShake = async () => {
        await setShake(true)
        await setShake(false)
    }

    return (
        <>
            {!isLoading ? (
                <Loading />
            ) : (
                <div className = "App">
                    <div className = "app-wrap">
                        <PageTitle />
                        <div className = "search-wrap">
                            <form onSubmit = {getSearch} className = "search-form">
                                <input
                                    className = "search-bar"
                                    type = "text"
                                    value = {search}
                                    onChange = {updateSearch}
                                />
                                <button type = "submit" className = "search-button">
                                    <FontAwesomeIcon
                                        icon = {faSearch}
                                        className = "search"
                                    />
                                </button>
                            </form>
                        </div>
                        <Cloud cloudhex = {cloudHex} shake = {shake} />
                    </div>
                </div>
            )}
        </>
    );
};

export default App;

Облако.js

import React, {useEffect} from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCloud } from "@fortawesome/free-solid-svg-icons";
import './cloud.css';

const Cloud = ({cloudhex, shake}) => {

    useEffect(() => {
        
    }, [])

    console.info(shake)
    return (
        <div className = {`cloud-wrap ${ shake ? "shake-cloud":''}`}>
            <span className = "cloudhexname">{cloudhex}</span>
            <FontAwesomeIcon icon = {faCloud} className = "cloud" style = {{color:`${cloudhex}`}} />
        </div>
    );
};

export default Cloud;
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
1 321
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Делай так

Если вы хотите отобразить облачный компонент после отправки формы, поставьте один флаг и переключите его, здесь я беру состояние clicked

import React, { useState, useEffect } from "react";
import "./App.css";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faSearch } from "@fortawesome/free-solid-svg-icons";
import "./search.css";
import PageTitle from "./component/PageTitle";
import Cloud from "./component/Cloud";
import Loading from "./component/Loading";

//https://api.color.pizza/v1/
//data.colors[0].name

const App = () => {
    const [isLoading, setIsLoading] = useState(false);
    const [colorNames, setColorNames] = useState("");
    const [search, setSearch] = useState("");
    const [query, setQuery] = useState("");
    const [cloudHex, setCloudHex] = useState("ivory");
    const [shake, setShake] = useState(false);
    const [clicked, setClicked] = useState(false);

    useEffect(() => {
        getColorLists();
    }, []);

    const getColorLists = async () => {
        const res = await fetch(`https://api.color.pizza/v1/`);
        const data = await res.json();
        await setColorNames(data);
        setIsLoading(true);
    };

    const isColor = () => {
        let makeUpper =
            query.search(/\s/) == -1
                ? query.charAt(0).toUpperCase() + query.slice(1)
                : query
                      .split(" ")
                      .map((i) => i.charAt(0).toUpperCase() + i.slice(1))
                      .join(" ");

        for (let i = 0; i < colorNames.colors.length; i++) {
            if (colorNames.colors[i].name == makeUpper) {
                setCloudHex(colorNames.colors[i].hex);
                return;
            } else if (i == colorNames.colors.length - 1) {
                return makeShake();
            }
        }
    };

    const updateSearch = (e) => {
        setSearch(e.target.value);
    };
    const getSearch = (e) => {
        e.preventDefault();
        setClicked(true);
        setQuery(search);
        isColor();
    };

    const makeShake = async () => {
        await setShake(true)
        await setShake(false)
    }

    return (
        <>
            {!isLoading ? (
                <Loading />
            ) : (
                <div className = "App">
                    <div className = "app-wrap">
                        <PageTitle />
                        <div className = "search-wrap">
                            <form onSubmit = {getSearch} className = "search-form">
                                <input
                                    className = "search-bar"
                                    type = "text"
                                    value = {search}
                                    onChange = {updateSearch}
                                />
                                <button type = "submit" className = "search-button">
                                    <FontAwesomeIcon
                                        icon = {faSearch}
                                        className = "search"
                                    />
                                </button>
                            </form>
                        </div>
                        {clicked && <Cloud cloudhex = {cloudHex} shake = {shake} />}
                    </div>
                </div>
            )}
        </>
    );
};

export default App;

Спасибо!! И с Рождеством ;)

Adorevoy 25.12.2020 15:50
Ответ принят как подходящий

Хороший подход в этом случае — использовать useRef() Hook для хранения значения нашего поля поиска вместо использования useState(). Потому что useRef()Hook does not force a re-render в то время как useState() делает. Этот подход известен как un-controlled способ использования поля ввода.

В основном вам нужно внести несколько изменений в свой код, а именно:

const search = useRef("");

Затем удалите onChange = {updateSearch} и value = {search} из input и используйте свойство ref = {search}. Так что ваш ввод выглядит следующим образом:

<input 
    className = "search-bar"
    type = "text"
    ref = {search}
/>

Затем в обработчике отправки вы можете получить значение поля ввода, используя search.current.value. Таким образом, ваш getSearch() будет выглядеть

const getSearch = (e) => {
    e.preventDefault();
    setClicked(true);
    setQuery(search.current.value);
    isColor();
};

Предположим, что пользователь ввел ввод. Если нет, то вы можете установить проверку перед использованием setQuery() в обработчике отправки формы getSearch().

if (search.current.value){
   setQuery();
}

Примечание. Если в вашем проекте есть какие-либо другие controlled inputs, вы можете изменить их на un-controlled с помощью refs, и таким образом в вашем коде не будет повторного рендеринга.

Вы наиболее наиболее Добро пожаловать. Мне нравится помогать людям. Господь Всемогущий АЛЛАХ дает мне мир и покой. Да, праздники идут хорошо. Надеюсь, у вас тоже все хорошо :)

Imran Rafiq Rather 25.12.2020 15:50

Другие вопросы по теме