Ответы пользователя по тегу React
  • Как лучше загрузить сайт на React на GitHub для доказательства, что он действительно на React?

    @tehfreak
    Github Pages это хостинг статических стайтов. И у него есть два режима работы:

    1. Хостинг из указанной ветки
    Можно руками закоммитить содержимое папки build в какую-то ветку, и выбрать эту ветку в качестве источника в настройках репозитория в разделе Pages.

    Это можно частично автоматизировать с помощью, например, этого инструмента.

    Вот пример команды для развертывания проекта на основе CRA (Create React App)

    "scripts": {
      "start": "react-scripts start",
      "build": "react-scripts build",
      "deploy": "npm run build && gh-pages -d dist"
    }


    2. Хостинг артефактов
    Можно полностью автоматизировать сборку и развертывание при коммите в репозиторий, написав сценарий с помощью Github Actions. В этом случае нужно выбрать Github Actions в качестве источника в настройках репозитория в разделе Pages.

    Вот пример автоматизации развертывания проекта на основе CRA

    Репозиторий с исходным кодом: https://github.com/tehfreak/example-react-cra-ghpa...
    Сценарий сборки и развертывания в этом репозитории: https://github.com/tehfreak/example-react-cra-ghpa...
    Собранный код доступен по этой ссылке: https://tehfreak.github.io/example-react-cra-ghpag...

    Вот пример автоматизации развертывания проекта на основе NextJS

    Репозиторий с исходным кодом: https://github.com/tehfreak/example-react-nextjs-g...
    Сценарий сборки и развертывания в этом репозитории: https://github.com/tehfreak/example-react-nextjs-g...
    Собранный код доступен по этой ссылке: https://tehfreak.github.io/example-react-nextjs-gh...

    В этих примерах сценарии максимально упрощены. В реальных проектах сценарии сборки и развертывания чуть сложнее. Но эти сценарии вполне можно использовать как есть для работы над небольшими пет-проектами.

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

    Я рекомендую автоматизировать развертывание. Happy hacking!
    Ответ написан
    2 комментария
  • Что значит такая запись tsx?

    @tehfreak
    Да, вы правильно думаете. Вот так это выглядит без использования _flowRight
    export default memo(withFiltering(withSorting(FieldList)))
    Ответ написан
    Комментировать
  • Нужно ли дробить страницу на компоненты, которые не несут в себе никакого функционала?

    @tehfreak
    В общем случае следует выносить в отдельные компоненты ради возможности переиспользования этих компонентов. А также ради инкапсуляции и локализации верстки и логики, в том числе чтобы упростить понимание родительского компонента.
    Ответ написан
    Комментировать
  • Когда и как надо закрывать вебсокет соединение фаирбейс?

    @tehfreak
    Фаирбейс сам управляет своим вебсокет-соединением. Приложение же управляет слушателями: подписывается на обновления базы данных когда это необходимо и отписывается когда обновления больше не требуется.

    Как-то так:
    import { doc, onSnapshot } from 'firebase/firestore'
    
    export default function EntitityPage({ entityId }) {
    
        const [ entity, setEntity ] = React.useState(null)
        
        React.useEffect(() => {
            const unsubscribe = onSnapshot(doc(db, 'entities', entityId), (snapshot) => {
                setEntity(snapshot.data())
            })
            return () => {
                unsubscribe()
            }
        }, [entityId])
        
        return (
            <div>{JSON.stringify(entity)}</div>
        )
    }
    Ответ написан
  • Как использовать setInterval для простейшего таймера?

    @tehfreak
    Все дело в замыкании. Переданная в setInterval функция замыкает в себе переменную seconds в значении ноль. Интервал работает, но при каждом следующем вызове функции переменная seconds имеет прежнее значение.

    В setSeconds нужно передать функцию, которая будет вызвана с актуальным значением seconds.

    Вот так:
    function App() {
        
        const [ seconds, setSeconds ] = React.useState(0)
    
        // старый вариант, не работает
        const startTimer = () => {
            setInterval(() => {
                setSeconds(seconds + 1)
            }, 1000)
        }
    
        // новый вариант, работает
        const startTimer = () => {
            setInterval(() => {
                setSeconds((seconds) => {
                    return seconds + 1
                })
            }, 1000)
        }
    
        return (
            <div>
                <button onClick={startTimer}>start</button>
                <h1>{seconds}</h1>
            </div>
        )
    }
    Ответ написан
    Комментировать
  • Как отрисовать данные которые приходят асинхроно?

    @tehfreak
    Вот полная версия требуемого компонента с индикатором загрузки и обработкой ошибки:
    class Lectures extends React.PureComponent {
    
        state = {
            lectures: null,
            lecturesError: null,
            lecturesPending: true,
        }
    
        async componentDidMount() {
            await this.fetchLectures()
        }
    
        async fetchLectures() {
            this.setState({ lectures:null, lecturesError:null, lecturesPending:true })
            try {
                const lectures = (await firebase.database().ref('lectures').once('value')).val()
                console.log(lectures)
                this.setState({ lectures, lecturesError:null, lecturesPending:false })
            } catch (lecturesError) {
                console.error(lecturesError)
                this.setState({ lectures:null, lecturesError, lecturesPending:false })
            }
        }
    
        render() {
            const { lectures, lecturesError, lecturesPending } = this.state
            return (
                <section>
                    <h1>Лекции</h1>
                    {lecturesPending && (
                        <div>Загружаются...</div>
                    )}
                    {lecturesError != null && (
                        <div>Не удалось загрузить: {lecturesError.message}</div>
                    )}
                    {lectures != null && (
                        <ul>
                            {lectures.map((lecture) => (
                                <li
                                    key={lecture.id}
                                >
                                    {lecture.name}
                                </li>
                            ))}
                        </ul>
                    )}
                </section>
            )
        }
    }
    Ответ написан
    Комментировать
  • Как записать данные из fireBase в state компонента React?

    @tehfreak
    Чтобы сразу записать данные в state (в конструкторе компонента), эти данные должны быть сразу доступны, например, в props. Если необходимо выполнить асинхронную операцию и записать результат в state, то делать это нужно в componentDidMount:

    class extends React.Component {
      async componentDidMount() {
        this.setState({
          data: (await dataRef.once('value')).val()
        })
      }
    }
    Ответ написан
    Комментировать
  • Скрыть блоки, если не помещаются полностью в родительский(React)?

    @tehfreak
    Вот этот пакет должен помочь: react-truncate-list.
    Там неоптимальное решение, но его вполне достаточно для списков с небольшим количеством карточек.
    Ответ написан
    1 комментарий