Ответы пользователя по тегу React
  • Ошибка с хуком useParams?

    @n1ksON
    мидл
    некорректная ссылка в запросе, повторяются кавычки, поэтому URL-адрес запроса локальный
    `"https://jsonplaceholder.typicode.com/users/${s}`
    Ответ написан
    Комментировать
  • Как правильно отрисовать классовую компоненту?

    @n1ksON
    мидл
    <NavLink to={'/profile/' + u.id}>
    <Route path='/profile:userId' element={<ProfileContainer />}/>
    Ответ написан
  • Можно и нужно ли подключать redux к модальным окнам?

    @n1ksON
    мидл
    мы делаем и так, и так. зависит от локальности модального окна.
    например, если это окно, открывается при нажатии на кнопку в одном каком-то месте, то нет смысла выносить это в redux.
    если это окно, всплывает в разных местах по какой-то глобальной причине, например доступа к странице нет, или залогиниться нужно или т.п., то конечно это нужно выносить в redux и диспатчить открытие/закрытие

    на практике, в наших проектах, чаще встречается второй вариант, так как одинаковые модальные окна приходится вызывать в разных местах. но лично я сторонник первого, мне кажется, что если есть возможность не вносить новые редьюсеры и не расширять глобальный стейт из-за очередной модалки, пробросив пару раз пропсы из основной компоненты в дочерние, то лучше сделать так. потому что в крупных приложениях глобальные стейты и так огромные с огромной кучей редьюсеров
    Ответ написан
    Комментировать
  • Где делать запросы на РЕАКТЕ?

    @n1ksON
    мидл
    Для начала можно и просто в основных компонентах вызывать useEffect, который будет обрабатывать запрос и с помощью useState хранить данные. А если их нужно использовать в каких-то дочерних компонентах, то через пропсы.

    В общем случае, используется стейт-менеджер, типа redux. Данные попадают в нужную компоненту напрямую с помощью useSelector, дальше при необходимости в "глупые" компоненты пробрасываются пропсы.
    Запросы из компонент диспатчатся и выполняются/организуются через redux-saga, например.
    Ответ написан
    Комментировать
  • Как правильно обработать данные get запрос?

    @n1ksON
    мидл
    Можете использовать useLayoutEffect, либо выполнять проверку на длину и показывать иное, типа:
    {array.length > 0 ? <div>content</div> : <div>empty</div>}
    Ответ написан
    1 комментарий
  • Redux toolkit. Почему не отрабатывает createAsyncThunk?

    @n1ksON
    мидл
    Не обернули редьюсеры combineReducers
    import { configureStore } from "@reduxjs/toolkit";
    import blog from "./slices/blogSlice";
    
    const rootReducer = combineReducers({
      blog: blog
    })
    
    export const store = configureStore({
      reducer: rootReducer
    });
    Ответ написан
    2 комментария
  • Как работать со слушателями событий в реакт?

    @n1ksON
    мидл
    Создаете компонент Header и выносите туда инпут и кнопку. Header импортируете в App. В Header с помощью props передаете функцию findUser и setInputValue.
    App.js
    function App() {
      const [userNickName, setUserNickName] = useState('');
      const [userProfile, setUserProfile] = useState('')
      const [repos, setRepos] = useState([])
      const [inputValue, setinputValue] = useState('')
      
      
      async function findUser() {
        setUserNickName(inputValue);
        let RespUserRepos = await (await axios.get('https://api.github.com/users/'+inputValue+'/repos')).data;
        let RespUser = await (await axios.get('https://api.github.com/users/'+inputValue)).data;
        setRepos(RespUserRepos);
        setUserProfile(RespUser)
      }
      
      return (
        <div>
          <Header findUser={findUser} setInputValue={setInputValue} />
          <Main>
            <Profile
              avatar={userProfile.avatar_url}
              name={userProfile.name}
              userNamel={userProfile.userName}
              followers={userProfile.followers}
              following={userProfile.following}
            />
            <ReposInfo title = {'Repositories'} reposNumber = {repos.length}>
            {repos.map((card) => <Card name={card.name} description={card.description} key = {card.name}/>)}
            </ReposInfo>
          </Main>
        </div>
      );      
    }

    Header.js
    const Header = ({ findUser, setInputValue }) => {
      return (
        <header>
          <button onClick={() => findUser()}>click me</button>
          <input  onChange={event => setinputValue(event.target.value)} />
        </header>
      )
    }
    Ответ написан
    1 комментарий
  • Как вызвать функцию у всех react компонентов нажатием на одну кнопку?

    @n1ksON
    мидл
    Создаете state в главном компоненте с помощью хука (или с помощью Redux), создаете там же функцию обновления state. Когда кнопка нажимается, должно сработать событие, которые вызовет функцию обновления state. И обновленные данные пробросьте с помощью props
    useState
    props
    Ответ написан
    Комментировать
  • Как работает передача картины с frontend к backend и как хранится в базы данных?

    @n1ksON
    мидл
    https://learn.javascript.ru/file
    Пример на React:
    const Component = () => {
      const fileReader = (e) => {
        let reader = new FileReader();
        const file = e.target.files[0]
        reader.readAsDataURL(file);
        reader.onload = () => {
          console.log(reader.result)
          // здесь инициализируем отправку изображения на сервер
        };
      }
      return (
        <div>
          <input type="file" accept='image/*' onChange={fileReader} />
        </div>  
      )
    }
    Ответ написан
    4 комментария
  • Почему получаю ошибку: GET http://localhost:8080/1/bundle.js net::ERR_ABORTED 404 (Not Found)?

    @n1ksON Автор вопроса
    мидл
    webpack.config.js
    const webpack = require('webpack');
    const path = require('path');
    
    const config = {
      entry: [
        'react-hot-loader/patch',
        path.resolve(__dirname, 'src', 'index.js')
      ],
      output: {
        path: path.resolve(__dirname, './dist'),
        filename: 'bundle.js',
        publicPath: '/'
      },
      module: {
        rules: [
          {
            test: /\.(js|jsx)$/,
            use: 'babel-loader',
            exclude: /node_modules/
          },
          {
            test: /\.css$/,
            use: [
              'style-loader',
              'css-loader'
            ]
          },
          {
            test: /\.svg$/,
            use: 'file-loader'
          },
          {
            test: /\.png$/,
            use: [
              {
                loader: 'url-loader',
                options: {
                  mimetype: 'image/png'
                }
              }
            ]
          }
        ]
      },
      resolve: {
        extensions: [
          '.js',
          '.jsx'
        ],
        alias: {
          'react-dom': '@hot-loader/react-dom'
        }
      },
      devServer: {
        historyApiFallback: true,
        contentBase: path.resolve(__dirname, './dist'),
        open: true,
        hot: true,
        compress: true,
      }
    };
    
    module.exports = config;

    index.html
    <!DOCTYPE html>
    <html>
        <head>
            <title>example</title>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
        </head>
        <body>
            <div id="app"></div>
            <script src='../bundle.js'></script>
        </body>
    </html>
    Ответ написан
    Комментировать
  • Как правильно пробросить между компонентами функционал?

    @n1ksON
    мидл
    Ну так вы в Setting обработчик chooseLang то передайте
    Ответ написан
    2 комментария
  • Как добавить класс active активному компоненту?

    @n1ksON
    мидл
    import React, { useState } from "react";
    
    export default function App() {
      const [state, setState] = useState([
        { id: 0, status: true },
        { id: 1, status: false }
      ]);
      const chooseItem = (id) => {
        const newArr = state.map((item) =>
          item.id === id ? { ...item, status: true } : { ...item, status: false }
        );
        setState(newArr);
      };
      return (
        <div className="App">
          {state.map((item) => (
            <div style={{ border: item.status ? "3px solid tomato" : "none" }}>
              <div>TABLE {item.id}</div>
              <button onClick={() => chooseItem(item.id)}>CLICK</button>
            </div>
          ))}
        </div>
      );
    }
    Ответ написан
    Комментировать
  • Как можно зарефакторить данный код?

    @n1ksON
    мидл
    - const onMouseKidsEnter = () => {
    -    setIsOpen('kids')
    -  }
    -  const onMouseWomenEnter = () => {
    -    setIsOpen('women')
    -  }
    -  const onMouseMenEnter = () => {
    -    setIsOpen('men')
    -  }
    + const onMouseParamEnter = (param) => {
    +  setIsOpen(param);
    + }


    <LeftBar>
    -       <LeftBarItem onMouseEnter={onMouseKidsEnter} onMouseLeave={onMouseLeave} isOpen={isOpen === 'kids'}>
    + <LeftBarItem onMouseEnter={() => onMouseParamEnter('kids')} onMouseLeave={onMouseLeave} isOpen={isOpen === 'kids'}>
              <span>Kids</span>
              <IoIosArrowBack />
            </LeftBarItem>
    -       <LeftBarItem onMouseEnter={onMouseWomenEnter} onMouseLeave={onMouseLeave} isOpen={isOpen === 'women'}>
    + <LeftBarItem onMouseEnter={() => onMouseParamEnter('women')} onMouseLeave={onMouseLeave} isOpen={isOpen === 'women'}>
              <span>Women</span>
              <IoIosArrowBack />
            </LeftBarItem>
    -        <LeftBarItem onMouseEnter={onMouseMenEnter} onMouseLeave={onMouseLeave} isOpen={isOpen === 'men'}>
    + <LeftBarItem onMouseEnter={() => onMouseParamEnter('men')} onMouseLeave={onMouseLeave} isOpen={isOpen === 'men'}>
              <span>Men</span>
              <IoIosArrowBack />
            </LeftBarItem>
          </LeftBar>

    А ещё лучше, <LeftBarItem> вынести в отдельный компонент и передавать туда нужный props с параметром kids/women/men
    Ответ написан
    1 комментарий
  • Подгрузка контента при доходе до конца блока?

    @n1ksON
    мидл
    import React, { useState } from 'react';
    import { useDispatch, useSelector } from 'react-redux';
    import Home from './pages/Home';
    
    const App = () => {
    	const dispatch = useDispatch();
    	const { data } = useSelector((store) => store);
    
    	const [allowScroll, setAllowScroll] = useState(true);
    
    	const scrolling = () => {
    		const height = Math.max(
    			document.body.clientHeight,
    			document.documentElement.clientHeight
    		);
    		if (
    			window.pageYOffset > height * 0.75 ||
    			window.pageYOffset > height - 2000
    		) {
    			if (allowScroll) {
    				setAllowScroll(() => false);
    				setTimeout(() => {
    					setAllowScroll(() => true);
    				}, 2000);
    				dispatch({
    					type: 'DISPATCH',
    				});
    			}
    		}
    	};
    
    	return (
    		<div onWheel={scrolling}>
    			<Home />
    		</div>
    	);
    };
    
    export default App;
    Ответ написан
    Комментировать
  • Как сделать Log Out при помощи firebase REST API?

    @n1ksON
    мидл
    curl 'https://identitytoolkit.googleapis.com/v1/accounts:update?key=[API_KEY]' \
    -H 'Content-Type: application/json' \
    --data-binary '{"idToken":"[FIREBASE_ID_TOKEN]","deleteProvider":["[facebook.com]"]}'

    Документация

    Вообще я в React использую firebase через npm и вам советую.
    Тогда работало бы так: firebase.auth().signOut()
    Ответ написан
  • Стоит ли использовать хуки вроде useState когда уже управляешь состоянием с помощью Redux?

    @n1ksON
    мидл
    Не используйте props для пробрасывания dispatch и store из redux. Для этого, как вы верно подметили, есть useSelector и useDispatch.
    1. useState очень даже нужен несмотря на использование redux. К примеру, у вас на сайте отображается уведомление при клике на кнопку. Зачем статус отображения уведомления выносить в redux? Redux, как верно заметили, это как глобальный store. В этом нет надобности, для статуса отображения (true/false) достаточно использовать useState внутри компоненты.
    2. Не совсем корректно сформулировали вопрос.
    Если у вас функция используется только в конкретной компоненте - храните в ней.
    Если функция используется в нескольких компонентах одного уровня - вынесите функцию на уровень выше, куда эти компоненты импортируются.
    Если функция часто используется в разных местах - вынесите её в отдельный файл (utils) и импортируйте в нужные компоненты.
    Вопрос: Говнокод ли вот эта колбаса?

    Не понятно, что она решает. Возможно можно написать чуть красивее или вообще на регулярных выражениях. Главное, чтобы решало необходимую задачу
    Ответ написан
    Комментировать
  • Как отобразить Loading... во время подгрузки?

    @n1ksON
    мидл
    setLoading должен меняться на false, только когда данные уже получены.
    А ещё вы key списку с репозиториями не задали, React ругается
    import React, { useState, useEffect } from "react";
    import Search from "./components/Search";
    import ReactPaginate from "react-paginate";
    import axios from "axios";
    import "./styles.css";
    const PER_PAGE = 4;
    const App = () => {
      const [user, setUser] = useState(null);
      const [currentPage, setCurrentPage] = useState(0);
      const [data, setData] = useState([]);
      const [loading, setLoading] = useState(false);
    
      async function getUser(login) {
        let result0;
        result0 = (await axios.get(`https://api.github.com/users/${login}`)).data;
        setUser(result0);
      }
    
      useEffect(() => {
        if (user) {
          setLoading(true);
          fetch(
            `//api.github.com/users/${user.login}/repos?page=${currentPage}&per_page=${PER_PAGE}`
          )
            .then((res) => res.json())
            .then(setData).then(() => setLoading(false));
        }
      }, [user, currentPage]);
      console.log(loading);
      function handlePageClick({ selected: selectedPage }) {
        setCurrentPage(selectedPage + 1);
      }
    
      /* const offset = currentPage * PER_PAGE;*/
    
      const currentPageData = data
        /* .slice(offset, offset + PER_PAGE)*/
        .map((post, i) => <p key={i}>{post.full_name}</p>);
    
      if (loading) {
        return <div class="loader">Loading...</div>;
      }
    
      if (user === null) {
        return (
          <div>
            <Search onSearch={getUser} />
            <div id="start">
              Start with searching
              <br />a GitHub user
            </div>
          </div>
        );
      } else if (user) {
        return (
          <div>
            <Search onSearch={getUser} />
            <ReactPaginate
              previousLabel={"← Previous"}
              nextLabel={"Next →"}
              pageCount={Math.ceil(user.public_repos / PER_PAGE)}
              onPageChange={handlePageClick}
              containerClassName={"paginatio"}
              previousLinkClassName={"paginatio__link"}
              nextLinkClassName={"paginatio__link"}
              disabledClassName={"paginatio__link--disabled"}
              activeClassName={"paginatio__link--active"}
            />
            <div id="cpd">{currentPageData}</div>
            <span id="repositories">Repositories({user.public_repos})</span>
          </div>
        );
      }
    };
    
    export default App;
    Ответ написан