Devo dizer imediatamente que o site funcionará mais rápido se você substituir o Bootstrap por CSS e JS puros. Este artigo é sobre como começar rapidamente a desenvolver aplicativos da Web bonitos e a otimização já é um problema separado que vai além do escopo deste artigo.
Primeiro, você precisa entender pelo menos um pouco de HTML, CSS, JavaScript, XML, DOM, OOP e poder trabalhar no terminal (linha de comando).
Onde conseguir materiais para estudo?Para aprender HTML e CSS, recomendo 
htmlbook.ruPara aprender JavaScript, recomendo 
learn.javascript.ruPara aprender XML, recomendo 
msiter.ru/tutorials/uchebnik-xml-dlya-nachinayushchihVocê pode ler sobre o DOM na lição JavaScript 
learn.javascript.ru/dom-nodesPara estudar OOP, recomendo o curso em vídeo 
proglib.io/p/oop-videocoursePara explorar a linha de comando do Windows, recomendo 
cmd.readthedocs.io/cmd.htmlPara estudar o terminal em um Mac, recomendo 
ixrevo.me/mac-os-x-terminalSe você está trabalhando no Linux, o 
bash e os análogos sabem que, em último recurso, o 
homem ou a 
ajuda o 
ajudarão .
Para aprender o React, uso 
learn-reactjs.ru (que é uma tradução da documentação oficial do React: 
reactjs.org ).
Para estudar o Bootstrap, eu uso o 
bootstrap-4.ru (que é uma tradução da documentação oficial do Bootstrap: 
getbootstrap.com ).
Para fazer amigos Reagir e Bootstrap, encontrei um excelente artigo 
webformyself.com/kak-ispolzovat-bootstrap-s-react Neste artigo, vou fazer um aperto no mínimo necessário para o trabalho e criar um cronômetro:

Instalação
Primeiro, precisamos de um gerenciador de pacotes. Eu escolhi o 
npm e está no 
Node.jsEntão, primeiro, instale o 
Node.js no seu sistema operacional a partir do site oficial: 
nodejs.org/en/download . Você pode descobrir a instalação, então não descreverei o processo de instalação. Notei apenas que a instalação no Ubuntu é simples:
sudo apt update sudo apt install nodejs sudo apt install npm 
Por meio do terminal, verificamos se o Node.js e o npm foram instalados com sucesso:
 nodejs -v npm -v 
Se houver erros durante a saída, significa que algo deu errado e você precisa entender, e é possível reinstalá-los. Se vc é exibido com números e pontos, tudo está bem.
Instale Create-react-app para que você possa criar rapidamente estruturas de aplicativos:
 npm install -g create-react-app 
Em seguida, criamos a estrutura do aplicativo no React. Vamos nomear nosso aplicativo como 
novo aplicativo . Se você deseja criar um aplicativo para uma pasta diferente da pasta do usuário, vá primeiro para o terminal através do terminal usando o 
comando cd . Então, no terminal, basta digitar 3 comandos:
 create-react-app new-app cd new-app npm start 
Criamos o 
aplicativo novo aplicativo . Vá para a pasta do 
novo aplicativo . Iniciamos o aplicativo. Após essas linhas, o navegador com o aplicativo React deve iniciar no endereço 
http: // localhost: 3000
O terminal deve permanecer aberto, sem ele a página do aplicativo não será aberta. Se você de repente fechou - isso não importa. Basta usar o 
comando cd para ir para a pasta do aplicativo e iniciá-lo com o comando 
npm startAgora instale o bootstrap
 npm install bootstrap 
Também é recomendável instalar as dependências jquery e popper.js, mas elas são necessárias apenas para a parte JS do Bootstrap. Eu tentei sem eles - a parte CSS do Bootstrap funciona bem, então as seguintes linhas no terminal são opcionais:
 npm install jquery popper.js 
Em seguida, é necessário fazer alterações nos arquivos do aplicativo, para isso, vá para a pasta new-app, onde o aplicativo está localizado, adicione a linha ao arquivo 
src / index.js , que deve ser o primeiro:
 import 'bootstrap/dist/css/bootstrap.min.css'; 
Se você usa jQuery, popper.js ou a parte JS do Bootstrap (janelas modais, animações etc.), será necessário adicionar mais três linhas na primeira linha:
 import $ from 'jquery'; import Popper from 'popper.js'; import 'bootstrap/dist/js/bootstrap.bundle.min'; 
Agora resta executar o projeto:
 npm start 
E, novamente, o navegador é aberto em 
http: // localhost: 3000 já com o aplicativo enobrecido usando o Bootstrap:

Também para depurar o React, você pode instalar a extensão " 
React Developer Tools " para o navegador. Os links atuais para a extensão do 
Chrome e 
Firefox e outros casos de uso estão listados no repositório oficial 
github.com/facebook/react-devtoolsA instalação e a configuração inicial estão concluídas.
JSX, componentes e propriedades
Vamos ver o que o 
create-react-app gerou para nós - os arquivos de origem estão no diretório src. Primeiro, vejamos o arquivo 
index.js - existem várias linhas de importação. Fica claro pelas linhas o que eles estão fazendo, então não vou comentar.
A linha mais importante neste arquivo:
 ReactDOM.render(<App />, document.getElementById('root')); 
Desenha a página do aplicativo. Há um elemento 
<div> com id = root no arquivo HTML de origem. Este 
<div> exibe o componente 
App , desenhado pela função de 
renderização da classe 
ReactDOM . Nesse caso, o componente é desenhado em um formato semelhante ao XML, chamado JSX (sobre o qual mais tarde).
Agora vamos para o arquivo 
App.js , onde está localizada a implementação da classe App, que herda da classe 
React.Component .
 class App extends React.Component {     <b>render()</b>,     JSX: <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer" > Learn React </a> </header> </div> 
JSX é muito semelhante ao HTML, mas há inserções de código JS entre chaves {}. E deve haver um elemento raiz, neste caso <div>.
Para entender melhor, apagaremos todo o código do método 
render () e escreveremos o componente mais simples:
 class App extends React.Component { render() { return <h1>, {this.props.name}!</h1>; } } 
Agora, vamos voltar ao arquivo index.js e corrigi-lo.
 ReactDOM.render(<App name="" />, document.getElementById('root')); 
Após salvar os arquivos, a página será atualizada no navegador. E agora vamos entender.
Conceitualmente, os componentes são semelhantes às funções JavaScript. Eles pegam dados arbitrários (chamados adereços) e retornam elementos React que descrevem o que deve aparecer na tela. Os componentes permitem dividir a interface do usuário em partes independentes e reutilizáveis e trabalhar com cada uma delas separadamente.
Quando o React vê que um elemento é um componente customizado, ele passa todos os atributos JSX para esse componente como um único objeto. Esse objeto é chamado de adereços.
No exemplo, o parâmetro 
name é passado para o componente como um atributo da 
tag <App> com o valor " 
World ". Além disso, no método 
render () da classe 
App , como resultado de uma função dentro do JSX, que na verdade é um modelo HTML, colchetes 
{} indicam 
isso - a classe atual, 
props - o objeto do usuário, 
nome - o nome do parâmetro do objeto.
Construtor, Ciclo de Vida e Mudança de Estado
Além dos parâmetros armazenados em 
adereços, você pode armazenar o estado do objeto em 
state .
Vamos fazer um cronômetro. Nenhum parâmetro é necessário para o timer, então vamos remover os parâmetros em 
index.js :
 ReactDOM.render(<App/>, document.getElementById('root')); 
E agora no arquivo 
App.js, substituímos todo o texto entre 
importação e 
exportação :
 const INTERVAL = 100; class App extends Component { constructor(props) { super(props); this.state = {value: 0}; } increment(){ this.setState({value: this.state.value + 1}); } componentDidMount() { this.timerID = setInterval(() => this.increment(), 1000/INTERVAL); } componentWillUnmount() { clearInterval(this.timerID); } render() { const value = this.state.value return ( <div> <p>:</p> <p> <span>{Math.floor(value/INTERVAL/60/60)} : </span> <span>{Math.floor(value/INTERVAL/60) % 60} : </span> <span>{Math.floor(value/INTERVAL) % 60} . </span> <span>{value % INTERVAL}</span> </p> </div> ); } } 
Após inserir e salvar esse código, um cronômetro aparecerá na página e iniciará automaticamente.
Vamos analisar esse código. Antes da aula, uma constante foi anunciada, graças à qual você pode ajustar a taxa de atualização do timer.
Em seguida, dentro da classe, há um construtor obrigatório da classe, para o qual os props são passados. Em seguida, o processamento padrão do construtor da classe pai 
super (props) e a determinação do estado do 
valor por meio 
disso é o objeto atual. Este é o único lugar onde você pode definir diretamente o estado. Em outros locais, apenas a leitura está disponível ou a configuração do estado com o método especial 
setState () , que é usado no próximo método 
increment () para aumentar o estado do 
valor em um.
Em aplicativos com muitos componentes, é muito importante liberar recursos ocupados por componentes quando eles são destruídos. Precisamos definir um cronômetro sempre que o DOM for sorteado pela primeira vez. No React, isso é chamado de "montar / instalar". Também precisamos limpar esse timer toda vez que o DOM criado pelo componente for excluído. Em React, isso é chamado de "desmontagem / desmontagem".
Para isso, os métodos 
componentDidMount () e 
componentWillUnmount () são usados . Na documentação, esses métodos são chamados de " 
ganchos do ciclo de vida ". Por simplicidade, os chamaremos de métodos de ciclo de vida. O método 
componentDidMount () é acionado após a renderização do componente no DOM. Este é um bom lugar para definir um cronômetro. Limparemos o cronômetro no método 
componentWillUnmount () do ciclo de vida.
Observe como em 
componentDidMount () armazenamos o ID do temporizador diretamente 
neste, usando a função de seta Enquanto this.props é instalado independentemente pelo React e 
this.state tem um significado específico, você pode adicionar livremente campos adicionais à classe manualmente se precisar armazenar algo que não é usado para saída visual. Se você não estiver usando algo em 
render () , ele não deve estar no estado 
state .
Além disso, durante a execução da 
renderização () , o estado do valor é fixo no valor constante local. E então, usando a função matemática 
floor () , que arredonda o número para baixo, dividindo ( 
/ ) e obtendo o restante da divisão ( 
% ), obtemos as partes do timer, que são exibidas na mesma linha após a palavra Timer. Você pode ver os resultados do nosso trabalho.
Aparência com o Bootstrap
Não é conveniente que o timer funcione imediatamente quando a página for atualizada. Gostaria que ele iniciasse e parasse quando você clicar nos botões apropriados. E eu gostaria que fosse no centro e grande.
Vamos começar com o design. Para fazer isso, adicione as seguintes linhas ao arquivo 
App.css :
 .container-fluid { display: flex; flex-direction: column; } 
Graças ao 
contêiner de borracha para 
contêiner adaptável do Bootstrap, que ajuda a criar um layout totalmente flexível para uma página ou bloco. Este contêiner é 100% largo. Vamos fazer um contêiner 
flexível , com a direção de alinhar os elementos verticalmente - para que ocupe todo o espaço e possa ser alinhado no centro.
Agora vamos finalizar o método 
render () no 
App.js para aplicar os estilos do Bootstrap e adicionar alguns botões. Para fazer isso, substitua o valor retornado pelo método pelo seguinte:
 <div class="container-fluid align-items-center"> <h1 class="display-1"></h1> <h1 class="display-1"> <span><kbd>{Math.floor(value/INTERVAL/60/60)}</kbd> : </span> <span><kbd>{Math.floor(value/INTERVAL/60) % 60}</kbd> : </span> <span><kbd>{Math.floor(value/INTERVAL) % 60}</kbd> . </span> <span><kbd>{value % INTERVAL < 10 ? '0' : ''}{value % INTERVAL}</kbd></span> </h1> <div> <button class="display-4"></button> <button class="display-4"></button> </div> </div> 
Na primeira linha, duas classes de Bootstrap foram adicionadas à raiz 
<div> : 
container-fluid (que escrevi acima) e 
align-items-center - que apenas alinha os elementos do container no centro.
Em seguida, dois 
<div> com a classe 
display-1 - essa classe é apenas para mostrar texto grande.
Em seguida, uma nova tag 
<kbd> foi adicionada aos números - que geralmente é usada para destacar as teclas que precisam ser pressionadas. Nesse caso, é ótimo para contrastar os números exibidos.
A expressão condicional é adicionada no último dígito, mostrando parte de um segundo, permitindo que dígitos de um dígito (<10) sejam exibidos no início de 0 e não para números de dois dígitos. Isso é necessário para que os números não se alterem a cada segundo. Para fazer isso, use o operador JavaScript ternário: 
condition? true: falseEntão, em um 
<div> separado, coloquei 2 botões com a classe 
Display-4 - essa classe foi selecionada como o tamanho mais adequado para que os botões correspondam ao tamanho do temporizador. Eu inseri um caractere entre os botões 
  - Espaço inextricável para que os botões não se fundam.
Você pode iniciar, mas os botões ainda não funcionam. Vamos ensinar os botões a trabalhar.
Manipulação de eventos
Primeiro, adicione a chamada às funções correspondentes no código de saída do botão:
 <button class="display-4" onClick={this.stopTimer}></button> <button class="display-4" onClick={this.resetTimer}></button> 
Observe que em React, o 
manipulador de eventos 
onClick , não 
onclick , como em JavaScript, e a função chamada são indicadas entre chaves sem parênteses e indicando o objeto do qual o método é chamado, neste caso, 
isso .
Agora, definimos os métodos especificados 
stopTimer () e 
resetTimer () :
 stopTimer(){ clearInterval(this.timerID); } resetTimer(){ this.setState({value: 0}); } 
Mas isso ainda não é suficiente, e se você deixar assim, quando o botão for pressionado, um erro aparecerá, porque isso ao chamar a função será 
indefinido . Isso ocorre porque, em JavaScript, os métodos de classe não são vinculados por padrão. Normalmente, se você referenciar um método sem () depois dele, por exemplo, 
onClick = {this.resetTimer} , será necessário vincular esse método.
Vincule os métodos no construtor da classe adicionando 2 linhas:
 this.stopTimer = this.stopTimer.bind(this); this.resetTimer = this.resetTimer.bind(this); 
Ótimo, funcionou! Mas apenas o botão Parar pode ser usado apenas uma vez e, depois disso, os botões param de funcionar. E isso é lógico, porque ao chamar 
stopTimer () , desabilitamos a chamada de função regular chamando 
clearInterval () .
Os comentários sugeriram o uso de funções de seta. Tentei funcionar. Portanto, você não pode adicionar 2 linhas ao construtor, mas substitua as próprias funções pelas seguintes funções de seta:
 stopTimer = () => { this.timerID = setInterval(() => this.increment(), 1000/INTERVAL); } resetTimer = () => { this.setState({value: 0}); } 
Para resolver isso, faremos com que o botão "Stop" também funcione como "Run".
Primeiro, adicione o estado booleano 
parado ao construtor para entender em que modo o botão funciona:
 this.state = {value: 0, stopped: false}; 
Agora substitua completamente o conteúdo do método 
stopTimer () :
 this.setState({stopped: !this.state.stopped}); if(this.state.stopped){ clearInterval(this.timerID); } else { this.timerID = setInterval(() => this.increment(), 1000/INTERVAL); }; 
No início do método, altere o estado 
parado para o oposto via 
setState () .
Além disso, se o timer deve ser parado (ou seja, 
parado = verdadeiro ), desativamos a chamada de função regular via 
clearInterval () e, se o timer deve ser iniciado (ou seja, 
parado = falso ), iniciamos a chamada de função regular da mesma maneira que 
componentDidMount () .
Você também precisa corrigir o método 
increment () para que ele pare quando 
parado = true :
 increment(){ if(!this.state.stopped) (this.setState({value: this.state.value + 1})); } 
E, finalmente, alteramos o nome do botão, dependendo do estado parado, inserindo o seguinte em vez de "Stop":
 {this.state.stopped?'':''} 
Agora temos um cronômetro bonito e conveniente.
Em vez de uma conclusão ou uma cereja no bolo
Finalmente, gostaria de mudar o título padrão e o ícone da janela para o nosso.
Você pode alterar o título definindo 
document.title no método 
componentDidMount () , mas prosseguiremos e tornaremos o tempo de exibição do título da página preciso em segundos. Para isso, adicionaremos a configuração 
document.title ao método 
componentDidUpdate () especial:
 componentDidUpdate(){ const value = this.state.value; if (this.state.stopped) document.title = ""; else document.title = ": "+Math.floor(value/INTERVAL/60/60)+":" +Math.floor(value/INTERVAL/60) % 60+":"+Math.floor(value/INTERVAL) % 60; } 
Agora, o timer repete até segundos no título da página e, quando o timer é parado, apenas a palavra Timer é exibida.
O ícone é simples. Basta preparar uma imagem no formato 
jpg , 
bmp , 
gif , 
png , soltá-la na pasta 
pública (e não no 
src , no qual trabalhamos principalmente), nomeie, por exemplo, 
favicon.png e altere a linha no arquivo 
public \ index.html :
 <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> 
por linha:
 <link rel="shortcut icon" type="image/png" href="/favicon.png"/> 
Por hoje, é tudo o que eu queria contar. No próximo artigo, falarei mais sobre o Bootstrap, que neste artigo tocou apenas um pouco. Além do Bootstrap, ainda existem tópicos importantes: listas, tabelas, formulários e pensamento no estilo React.
Por fim, o repositório no BitBucket, que possui todo o código deste artigo