Manual Front end
Este guia aborda práticas de desenvolvimento frontend no Sentry, com foco nos repositórios Sentry e Getsentry. Pressupõe o uso das regras ESLint definidas no eslint-config-sentry.
Estrutura de Diretórios
O código frontend está localizado em src/sentry/static/sentry/app e static/getsentry.
Organização de Pastas e Arquivos
Nomenclatura de Arquivos
Nomeie arquivos de forma descritiva conforme sua funcionalidade. Evite prefixos desnecessários.
Uso de index.(j|t)?(sx)
Utilize arquivos index apenas quando representarem pontos de entrada de componentes agrupados. Não crie re-exports desnecessários.
React
Definição de Componentes
class Observacao extends React.Component {
static propTypes = {
autor: PropTypes.object.isRequired,
aoEditar: PropTypes.func.isRequired,
};
manipularMudanca = valor => {
const usuario = ConfigStore.obter('usuario');
if (usuario.ehSupervisor) {
this.props.aoEditar(valor);
}
};
render() {
const { conteudo } = this.props;
return <div onChange={this.manipularMudanca}>{conteudo}</div>;
}
}
Componentes vs Views
components/ contém elementos reutilizáveis, enquanto views/ agrupa componentes específicos de UI.
PropTypes
Use formatos explícitos e prefira tipos personalizados compartilhados:
PropTypes.shape({
usuario: PropTypes.string.isRequired,
email: PropTypes.string
})
CSS e Emotion
import styled from '@emotion/styled';
const ComponenteEstilizado = styled('div')`
border-radius: 1.45em;
z-index: ${p => p.tema.zIndex.modal};
color: ${p => p.tema.roxo};
`;
Gerenciamento de Estado
Utilizamos Reflux para estado global, mas avaliamos alternativas.
Testes
Estamos migrando para React Testing Library. Exemplo básico:
import { render, screen } from 'sentry-test/reactTestingLibrary';
test('exibe mensagem de erro', async () => {
render(<Componente />);
expect(await screen.findByRole('alert')).toBeInTheDocument();
});
Novos Recursos de JavaScript
Encadeamento Opcional
const cidade = usuario?.endereco?.cidade;
Operador de Coalescência
const volume = config.volume ?? 0.5;
TypeScript
DefaultProps em Componentes
type Props = {
nome: string;
tamanho?: 'P' | 'M' | 'G';
};
const Planeta = ({ nome, tamanho = 'M' }: Props) => {
return <p>{nome} é um planeta {tamanho.toLowerCase()}</p>;
};
Hooks
Prefira hooks para nova lógica de estado:
const [estado, definirEstado] = useState(null);
useEffect(() => {
buscarDados().then(definirEstado);
}, []);
Migração Grid-Emotion
Substitua componentes por equivalentes Emotion:
const Flex = styled('div')`
display: flex;
`;
const Box = styled('div')``;