Redux: Solicitação de discussão: Redux "boilerplate", curva de aprendizado, abstração e teimosia

Criado em 19 mar. 2017  ·  108Comentários  ·  Fonte: reduxjs/redux

Resolução: use o Redux Starter Kit

As ideias neste tópico eventualmente se transformaram em nosso novo pacote Redux Starter Kit . Inclui utilitários para simplificar muitos casos de uso comuns do Redux, incluindo configuração de loja, definição de redutor, lógica de atualização imutável e até mesmo a criação de "fatias" inteiras de estado automaticamente sem escrever nenhum criador de ação ou tipo de ação manualmente.

Para obter mais detalhes sobre quais problemas o Redux Starter Kit deve resolver (e o que ele _não fará), consulte o manifesto "Visão para Redux Starter Kit" que escrevi .

A reclamação número um que vejo sobre o Redux é que há "clichês demais". Também vejo frequentemente reclamações de que há muito para aprender, muitos outros addons que são necessários para fazer algo útil e muitos aspectos onde o Redux não tem nenhuma opinião e, portanto, não oferece nenhum tipo de orientação embutida.

Acabei de discutir com @tannerlinsley sobre vários desses aspectos. Discutimos a biblioteca Jumpstate , que é uma camada de abstração em torno do Redux, e como ela pretendia facilitar a curva de aprendizado, bem como várias opiniões filosóficas sobre o que constitui um "bom" uso do Redux.

A partir daí, levantamos várias questões que gostaria de apresentar para uma discussão mais ampla:

Pontos chave

Boilerplate / Verbosity

  • Redux não pretende ser a "maneira mais concisa de fazer as coisas", mas sim tornar o fluxo de dados óbvio e legível
  • Os documentos são escritos em um estilo deliberadamente prolixo para maior clareza e aprendizado, e não têm a intenção específica de ser "a única maneira verdadeira de escrever código Redux", mas esse estilo foi adotado cegamente (ou, às vezes, resultou na rejeição de Redux)
  • Reclamações frequentes sobre "clichês", como "muitos arquivos", "uso de criadores de ação", etc.

Abstrações e Aprendizagem

  • A biblioteca principal do Redux está completa com todos os recursos, mas há muitos complementos e ferramentas interessantes sendo construídos pela comunidade
  • Várias bibliotecas de abstração foram construídas para "facilitar a curva de aprendizado" ou "tornar as coisas mais OOP", mas a maioria delas não são realmente "idiomáticas" de uso do Redux
  • A curva de aprendizado do Redux pode ser íngreme, mas uma vez que você entende os conceitos, a necessidade de camadas de abstração geralmente desaparece

Problemas

  • Sobre o que são as reclamações "padronizadas" principalmente?
  • Quais são os aspectos mais difíceis do Redux para novos alunos?
  • Quais são as áreas "sem opinião" que causam problemas para as pessoas?

Soluções Potenciais

  • Como seria o uso idiomático do Redux com "menos padrão"? Como podemos fornecer soluções para essas reclamações?
  • Quais abstrações possíveis poderiam ser criadas para simplificar o processo de aprendizado e uso, mas sem realmente ocultar o Redux (e, com sorte, forneceria um caminho de migração / aprendizado para o Redux "básico")?
  • Quanto disso poderia ser resolvido com documentos aprimorados de alguma forma?

Gostaria de convidar a comunidade a oferecer reclamações, pontos fracos e preocupações sobre o uso do Redux e, espero, também fornecer sugestões e ideias para resolver esses problemas também.

Comentários muito úteis

Se dependesse de mim, gostaria de ver isto:

  • Um subconjunto amigável de Flow / TypeScript que é mais fácil de digitar do que o Vanilla Redux.
  • Não enfatizar muito as constantes (apenas torne o uso de literais de string mais seguro).
  • Manter a independência do React ou de outras bibliotecas de visualização, mas tornando mais fácil usar os vínculos existentes (por exemplo, fornecendo mapStateToProps implementações).
  • Preservando os princípios do Redux (ações serializáveis, viagem no tempo e recarregamento a quente devem funcionar, o log de ação deve fazer sentido).
  • Oferecer suporte à divisão de código de uma maneira mais direta e pronta para uso.
  • Incentivando a colocação de redutores com seletores e tornando-os menos difíceis de escrever juntos (pense em pacotes de seletores de redutor que são fáceis de escrever e compor).
  • Em vez de colocar criadores de ação com redutores, livrar-se completamente dos criadores de ação e tornar natural o mapeamento de muitos para muitos de ações para redutores (em vez de fugir disso como a maioria das bibliotecas).
  • Tornar padrões de desempenho razoáveis ​​para que a memorização por meio de Selecionar novamente “simplesmente funcione” para casos de uso comuns, sem que os usuários escrevam esse código.
  • Contendo auxiliares integrados para indexação, normalização, coleções e atualizações otimistas.
  • Tendo suporte de fluxo assíncrono testável integrado.

Acima de tudo, é claro, embora não haja problema em marcá-lo como uma coisa oficial do Redux.
Além disso, não vou escrever isso. Mas você pode.

Todos 108 comentários

Algumas ideias:

  • pacote redux-preset oficial contendo redux, react-redux, redux-thunk já conectados juntos
  • dispatch(actionType, payload) poderia reduzir a necessidade de criadores de ação
  • criadores de redutores integrados ao estilo jumpstate, por exemplo, createReducer({[actionType]: (state, payload) => state}, initState)

A maioria das pessoas que conheço que usam redux intensamente acabam se afastando do redux-thunk, pois descobrem que ele não é escalonado muito bem e acaba levando a criadores de ação que começam a fazer demais, e preferem usar outra coisa para gerenciar o lado -efeitos como redux-observable ou redux-saga.

Eu posso entender o apelo nele, especialmente quando comecei a redux - mas não tenho certeza se empacotá-lo como parte de um 'pacote padrão de melhores práticas' seria a melhor ideia.

Portanto, esta parte é a mais crítica para mim (não serão tanto ideias para resolver o problema, mas sim restrições que são, pelo menos para mim, importantes):

Redux não pretende ser a "maneira mais concisa de fazer as coisas", mas sim tornar o fluxo de dados óbvio e legível

Uma grande coisa sobre Redux é como ele é quase mais um padrão de design do que um framework, e todo o código que você vê (exceto para a loja e react-redux ) é seu.

Olhando para Jumpstate (eu não sabia sobre isso até agora), é uma das primeiras camadas de abstração que vejo para Redux que parece bom. Ótimo mesmo! Mas, ao mesmo tempo, ele o deixa a apenas um fio de distância de outros frameworks como o MobX, e ter vários frameworks que trazem a mesma coisa para a mesa não é muito útil. Portanto, focar no que torna o Redux diferente do resto é importante, não apenas em como podemos tornar o Redux melhor no vácuo (porque ele vive no mesmo mundo que outras ferramentas).

Outra coisa importante, é que muitos dos desafios que os novatos enfrentam quando chegam ao Redux não são o Redux em si, mas o JavaScript. Outros grandes frameworks como o abstrato Angular eliminam o próprio JavaScript. Escrever um redutor Redux é simplesmente aplicar "padrões de design" vanilla javascript, que podem não ser familiares para os novatos e farão com que as pessoas queiram usar uma caixa preta em seu lugar.

Finalmente, muitas bibliotecas de redução padrão tentam adicionar uma relação 1: 1: 1 entre componentes, redutores e criadores de ação (talvez não todos os 3, mas geralmente 2 deles), o que faz os novatos esquecerem que podem ter vários redutores lidando com uma ação , vários componentes usando o estado de vários redutores e assim por diante. Essa é uma das perguntas nº 1 que eu respondo no trabalho e em outros lugares, e é muito útil. Portanto, a ferramenta para ajudar nessa área não deve perder isso (além disso, "mudar são nojentos" não é o melhor argumento do mundo).

Portanto, IMO, CTAs envolveriam vincular bons recursos de JavaScript vanilla, bem como documentar mais do "por que" junto com os conceitos de "primeiros passos" e manter as coisas simples. Você pode construir aplicativos gigantescos no Redux sem aprender muitos conceitos novos. Embora eu mesmo seja um cara redux-observável, já vi centenas de milhares de linhas de aplicativos de código usando Thunk sem problemas (e já vi aplicativos minúsculos naufragar com thunks). Introduzir poucos conceitos "centrais" e mostrar como eles podem ser aplicados a toneladas de conceitos ajuda muito.

O "todos os boilerplates devem ser reduzidos, não importa o custo" é um problema com a comunidade de engenharia de software como um todo atualmente ... isso é mais difícil de resolver.

Desde o início, minha principal preocupação com redux era que ou eu lesse ou escrevesse um código, eu tivesse que pular entre N arquivos, a lógica b / c da única parte da IU está espalhada por todo o código-base entre ações, tipos de ação e vários redutores. Eu realmente gosto de poder chegar a qualquer parte da árvore de estado de qualquer lugar na IU e posso alterar as diferentes partes do estado em resposta a uma única ação (principais razões pelas quais eu uso redux), mas as partes mais Quanto mais mudo de estado em resposta a uma única ação, mais minha lógica é manchada. Não posso simplesmente ler ou escrever o que aconteceu quando o usuário fez isso ou aquilo. Mas o que eu quero é pode ser descrito assim:

// meta code
dispatch(ACTION);

onAction = {
  ACTION: [
    // handler 1: hide spinner here,
    // handler 2: change status there,
    // handler 3: update entity
  ],
};

No final, criei redux-interactions + redux-tree e estou muito feliz com isso até agora.

Abordagem em nosso projeto atual:

note, seria muito diferente dependendo dos requisitos do aplicativo :) uma vez que adicionamos atualizações de objetos em tempo real, talvez sagas ou observáveis ​​forneçam benefícios em relação à conversão / promessa

  • redux-thunk
  • prometer middleware
  • nosso "api wrapper", que é um wrapper em torno do aplicativo de penas do cliente, service(name, method, ...opts) que é um criador de ação com a carga útil sendo uma promessa de chamar nossa API (ou seja, o middleware de promessa pega e envia x_FULFILLED , x_PENDING e x_REJECTED ). também pode sobrescrever o nome da ação para isso.

Primeiro usamos componentDidMount() para chamar nossa API, armazenar dados no estado do componente. No entanto, usamos nosso api wrapper para isso, o que significa que uma ação ainda é enviada (e registrada pelo middleware logger, incluindo meta que é a informação de solicitação), e se desejarmos refatorar para usar o armazenamento para esse componente, tudo o que precisamos é adicionar um redutor que escuta a ação. Começamos usando apenas o estado local e refatoramos para redux quando o estado daquele componente precisa ser acessado / modificado de outro componente. Dito isso, vejo a atração de usar o redux em todos os lugares, pois ele fornece uma trilha de papel para tudo. Dada a nossa equipe atual e cronograma de aplicação, simplesmente não é benéfico para nós, atm.

Eu brinquei com a saga redux um pouco, mas como nosso fluxo assíncrono mais complicado é login / logout, que funciona (e o código não é terrivelmente complicado), não é um grande motivo para mudar (mas pode valer a pena para o teste motivos - iteráveis ​​+ simulações são uma boa maneira de testar). redux-observable Não vejo o benefício imediato, a menos que os observáveis ​​forneçam benefícios, por exemplo, se você deseja clicar duas vezes em eventos bem.

Ficamos um pouco longe do clichê por ter nossas próprias funções de fábrica para retornar redutores e nossos próprios redutores de ordem superior em cima da funcionalidade personalizada (por exemplo, um redutor em cima de "paginator" para que o conteúdo seja paginado, mas pode ter um personalizado ações para modificar um item).

O que eu acho que precisa ser feito é um tutorial gigante trabalhando a partir de um aplicativo de reação básico, demonstrar os problemas que surgem com a comunicação entre os componentes, em seguida, introduzir redux e, em seguida, prosseguir, demonstrando os problemas que ocorrem em situações específicas e como eles podem ser ajudado com redux-x . Ou seja, um guia de quando e o que usar. Definitivamente, existem algumas postagens de blog com discussão nessa direção.

O que também é relevante é o meu resumo que criei para os padrões usados ​​em

A maioria das pessoas que conheço que usam redux intensamente acabam se afastando do redux-thunk, pois descobrem que ele não escala muito bem

Eu entendo o que você está dizendo, mas aqui está minha outra preocupação: estamos vendo mais e mais evidências anedóticas de que um grande grupo de desenvolvedores JS ainda não está usando _funções de seta_ e outros recursos ES (6 | 2015) de linha de base ainda , devido à falta de compreensão, intimidação, etc. Esperando que as pessoas que querem começar com o Redux, e que poderiam se beneficiar aprendendo os _padrões_ que o Redux introduz, primeiro aprendam observáveis ​​ou geradores, eu acho que provavelmente está pedindo demais?

Redux-thunk também é um pouco complexo no sentido de que o middleware redux em geral meio que dobra seu cérebro, mas é pelo menos apenas funções / callbacks, que são fáceis de entender se você estiver escrevendo JS. Eu realmente gosto da ideia de ter um pacote completo de ferramentas relacionadas para começar, disponível através de um único download, mesmo que seja apresentado como "learn-redux" em vez de "best-practice-always-redux". Semelhante a como criar-reagir-app precisa de ajustes conforme você aprende todas as coisas que ele configurou para você, isso pode encorajar seus próprios ajustes, talvez mostrar como converter uma configuração simples de redux-thunk para usar sagas, etc. como sua própria forma de "ejetar" ...

Apenas alguns pensamentos.

Eu entendo o que você está dizendo, mas aqui está minha outra preocupação: estamos vendo mais e mais evidências anedóticas de que um grande grupo de desenvolvedores de JS ainda não está usando funções de seta e outros recursos ES (6 | 2015) de linha de base ainda , devido à falta de compreensão, intimidação, etc. Esperando que as pessoas que querem começar com o Redux, e que poderiam se beneficiar aprendendo os padrões que o Redux introduz, aprendam primeiro observáveis ​​ou geradores, acho que provavelmente está pedindo demais?

Bingo! Estamos em um ambiente onde MUITAS pessoas são novas em JS (ou "conhecem" JS, mas não é sua especialidade e elas começam do fundo do poço). Especialmente se essas pessoas forem engenheiros de software experientes de outro ecossistema (java, rails, etc), eles vão tentar aplicar rapidamente os conceitos que conhecem antes de aprender os que não conhecem, e não funcionará muito bem e eles ficarão presos. Não sei qual é a melhor maneira de convencer as pessoas a obter um entendimento profundo de JS antes de pular em um padrão de design UX funcional.

Observe que os documentos do Redux têm uma seção sobre Redução do Boilerplate para aqueles que estão lendo e estão procurando por algo agora e não querem adotar uma biblioteca inteira em cima do Redux.

Devemos ter um pouco de cuidado com essa discussão e perceber que isso provavelmente já foi muito usado. A equipe Redux ouviu, considerou e rejeitou muitas coisas que provavelmente serão propostas aqui. É bem possível que nada saia dessa discussão se apenas brigarmos por coisas que já foram discutidas.

Dito isso, acho uma ótima ideia falar sobre maneiras de tornar o framework mais acessível a todos (novos e experientes).

Qualquer coisa que você propor para reduzir o boilerplate deve ser tal que seja possível voltar para o material abaixo da abstração sempre que necessário. Não é divertido adotar uma abstração apenas para largá-la mais tarde para voltar às coisas de nível inferior, porque você precisava de uma coisa extra em que os autores da abstração não pensaram.

A curva de aprendizado do Redux pode ser íngreme, mas uma vez que você entende os conceitos, a necessidade de
camadas de abstração geralmente desaparecem

Estou pensando, se for esse o caso, quais partes do Redux estamos sugerindo melhorar? Quais partes você removeria ou abstrairia que não precisaria adicionar imediatamente?

Este é um diagrama de todo o ciclo de vida reac / redux que fiz para uma palestra no trabalho há cerca de um ano:
React Redux Lifecycle

Existem algumas partes disso, mas não consigo imaginar o Redux funcionando tão bem sem nenhuma delas. Os contêineres são meio irritantes às vezes, mas se você removê-los, você acopla profundamente sua lógica de visualização com seu layout de dados. Se você remover ações, você é basicamente um MVC novamente, o que está perdendo o ponto de usar Redux em primeiro lugar. A "visão" nesse diagrama mal existe porque pode ser modelada apenas como uma função que assina a loja e renderiza os componentes de reação.

Não acho que haja muitos clichês a serem removidos no próprio framework geral. Talvez você esteja se referindo ao clichê nas partes individuais da estrutura, como criadores de ação, redutores ou contêineres. Nesse caso, as dicas da página Reducing Boilerplate mencionada acima já abordam a maioria dessas coisas. Não precisamos de nada além disso para torná-lo "melhor". (Observação: não é que eu não esteja aberto a adicionar algo para tornar as coisas melhores, só não vejo isso ainda.)

Talvez isso não seja tanto um problema de redução do clichê, mas um problema de melhorar a educação do Redux. Se o framework é difícil de entender para iniciantes, podemos precisar melhorar a documentação do Redux e torná-la mais acessível. Talvez algumas das dicas padronizadas de redução precisem ser anunciadas de forma mais agressiva nos documentos.

Reduzir a quantidade de etapas necessárias (clichê) nem sempre resolve o problema. Para enfatizar meu ponto desde o início de minha postagem, você não quer escrever uma abstração que será jogada fora porque você não pensou em todas as maneiras como as pessoas precisariam usá-la.

Boa discussão até agora. Deixe-me citar alguns exemplos rápidos de reclamações comuns relacionadas ao "clichê" que vejo:

  • "Por que tenho que escrever funções de 'criador de ação' apenas para retornar um objeto imediatamente?"
  • "Tenho que mexer em MUITO muitos arquivos apenas para adicionar um novo recurso simples! Além disso, fico repetindo os mesmos nomes continuamente para constantes e nomes de função e ..."
  • "Por que preciso dessas coisas de 'middleware' apenas para fazer uma chamada AJAX?"
  • "Por que eu tenho que usar declarações switch para tudo?"
  • "Por que preciso dessa coisa dispatch ? Por que preciso agrupar todas essas funções para fazê-las funcionar?"

E alguns exemplos específicos desses tipos de comentários:

E para lançar imediatamente algumas respostas a essas preocupações "estereotipadas": das cinco categorias listadas, apenas "uso de dispatch " é realmente _requerido_. Para o resto:

  • Você _não tem que usar criadores de ação, mas é uma boa prática para manter a consistência (de acordo com meu post
  • Você _não precisa_ de arquivos completamente separados para criadores de ações, constantes de ações e redutores. O padrão "patos" é uma abordagem popular para colocar tudo isso em um arquivo. Isso tem a desvantagem de "ocultar" a capacidade de vários redutores ouvirem uma ação. No final das contas, o Redux não se importa com a estrutura de seus arquivos.
  • Você _pode_ fazer trabalho assíncrono fora do Redux completamente, como em um componente. Mas, de acordo com a descrição de Dan em Por que precisamos de middleware para fluxo assíncrono no Redux? , geralmente é bom extrair essa lógica fora dos componentes, e o middleware fornece uma "brecha" para fazer trabalho assíncrono enquanto tem acesso ao armazenamento Redux.
  • Você definitivamente _não_ precisa usar instruções switch em redutores, eles são apenas a maneira mais "óbvia" de lidar com vários valores para uma determinada variável. Tabelas de pesquisa, instruções if / else e qualquer outra coisa que você quiser estão bem (por FAQ: Devo usar instruções switch? )
  • Você _não_ precisa realmente chamar store.dispatch() para fazer qualquer coisa útil acontecer - essa é uma decisão de design básica do Redux. Vincular criadores de ação torna possível passá-los para componentes filhos desconectados e ainda despachá-los sempre que a função é chamada.

Portanto, no geral, não há quase nada fora dessas preocupações "clichê" que seja _requerido_. É uma combinação de exemplos dos documentos e "boas práticas de programação", como eliminação de duplicação de código e separação de interesses.

Acho que as perguntas levantadas por @markerikson são realmente justas e eu mesmo as fiz em algum momento no passado.

Redux é, em certo sentido, uma biblioteca de "baixo nível" para modelagem de dados. Como qualquer biblioteca de baixo nível, ela expõe muitas coisas que você pode facilmente abstrair para dar conta da maioria dos casos. Acho que @gaearon não fez isso originalmente é porque ele queria manter a biblioteca o mais pequena e flexível possível. Graças a essa decisão, somos capazes de construir muitas coisas diferentes em cima do Redux sem precisar ter tudo no núcleo do Redux.

Talvez devêssemos considerar que o caminho certo seria desenvolver e estabilizar uma boa biblioteca em cima do Redux (como Jumpstate?). Começamos ensinando isso às pessoas e, em seguida, oferecemos a elas um caminho fácil para usar o Redux diretamente quando necessário.

Não acho que o Redux precise de muito mais em sua base de código principal e não vejo nenhuma parte dele que precise ser abstraída permanentemente. (Se você fizer isso, me diga: smile :) Na minha opinião, não há muito a ganhar adicionando ou removendo coisas do núcleo do Redux.

Melhorar uma biblioteca a ponto de ser estável e flexível o suficiente para que todos possam usar é provavelmente a melhor opção. Como você disse, não muito do "clichê" é realmente necessário , então vamos nos livrar dele em uma biblioteca em cima do Redux ao invés de modificar o próprio Redux.

Um exemplo disso acontecendo em outra comunidade está na linguagem de programação Rust. Existe uma biblioteca IO sem bloqueio para a linguagem de programação Rust chamada "mio" . Ele se concentra em ser pequeno e de baixo nível, assim como o Redux faz. A questão é que praticamente ninguém usa diretamente porque seria muito difícil e cheio de clichês. Quase todo mundo usa outra biblioteca chamada tokio, que se baseia no mio e o torna extremamente utilizável e ergonômico. Dessa forma, qualquer pessoa que precise do encanamento da mio pode usá-lo diretamente, mas quem quiser apenas fazer algo rápido pode usar o tokio.

Devemos adotar um modelo semelhante.

Para expandir alguns comentários de @sunjay :

Houve um comentário recente no nº 775 que acho que captura bem as coisas:

Redux é uma estrutura genérica que fornece um equilíbrio entre estrutura suficiente e flexibilidade suficiente. Como tal, ele fornece uma plataforma para que os desenvolvedores criem gerenciamento de estado personalizado para seus casos de uso, enquanto podem reutilizar coisas como o depurador gráfico ou middleware.

Então, sim, Redux é "apenas um padrão" de várias maneiras. A biblioteca central realmente possui recursos completos - as únicas mudanças semi-planejadas reais são coisas como a reestruturação do intensificador proposta (# 1702, # 2214) e, possivelmente, tornando combineReducers mais flexível (# 1768, # 1792, etc. )

Quase dois anos se passaram desde que o Redux foi criado, e agora temos uma boa ideia de como as pessoas o estão usando. Como um exemplo, @jimbolla coletou uma lista de todos os aprimoradores de loja conhecidos em # 2214 e categorizou como eles funcionam e para que são usados. Ainda sou um grande fã da simplicidade e flexibilidade do Redux, mas adoraria ver algumas abstrações ainda idiomáticas em cima do Redux que simplificariam o uso geral e resolveriam problemas para as pessoas.

Um outro conjunto de tópicos semirrelacionados, e algo em que tenho um interesse pessoal distinto, são as idéias de "lógica / componentes encapsulados" (de acordo com o playground "scalable frontend with Elm / Redux" de @slorber ) e "plug -and-play Redux setup "(como visto em experimentos como https://github.com/brianneisler/duxtape/issues/1, https://github.com/jcoreio/redux-features/issues/7, etc). O estado global e a configuração do aplicativo são ótimos para alguns casos de uso, mas não tanto para outros.

Como um ponto interessante relacionado, @toranb fez um ótimo trabalho criando um wrapper Ember para Redux em https://github.com/ember-redux/ember-redux . O mundo Ember está _realmente_ em "convenção sobre configuração", então ember-redux define uma configuração de loja padrão razoável, incluindo redux-thunk e outros semelhantes. Algum tipo de abordagem como essa pode ser útil.

Então, sim, estou de certa forma lançando um monte de pensamentos diferentes aqui, mas eles estão relacionados de várias maneiras. No geral, quero diminuir as barreiras para aprender e usar o Redux e permitir casos de uso mais avançados em toda a linha.

Redux é uma API geral, não especializada. Isso o torna mais detalhado, ao mesmo tempo que cobre mais casos. Seu poder está em software complexo, enquanto qualquer projeto novo ou simples está além do escopo da necessidade.

No entanto, você pode criar especializações com base em APIs gerais. Por exemplo, eu uso https://github.com/acdlite/redux-actions que reduz o boilerplate para casos comuns. Ainda uso todo o poder do redux e simplesmente ter essa interface não seria suficiente para minhas necessidades.

O outro problema é com pessoas novas que não experimentaram a dor de aplicativos incrivelmente complicados e se perguntam qual é o objetivo. Bem, para eles, eles provavelmente não deveriam nem mesmo usar o redux antes de sentirem aquela dor, mas a série egghead de Dan pode chutá-los além desse ponto com bastante facilidade.

https://egghead.io/courses/getting-started-with-redux
https://egghead.io/series/building-react-applications-with-idiomatic-redux

Referência: O espectro de abstração: https://www.youtube.com/watch?v=mVVNJKv9esE

Como mencionado - redux-actions é muito bom em remover alguns clichês, remover constantes da equação anexando .toString é uma ideia muito legal de que gosto, no entanto, prefiro escrever essa lógica sozinho do que usar redux-actions eu mesmo, mas essa é a escolha pessoal para manter meu código menor.

Imho, deve haver um mecanismo embutido (argumento de retorno de chamada de subscribe ?) Para observar o fluxo de ações despachadas (eu sei que pode ser feito em um middleware, mas isso restringe bastante o caso de uso, pois não pode ser usado fora, ou seja, por componentes ou connect )

Muitas vezes eu ensino redux para outras pessoas e pode ser bastante assustador pelos seguintes motivos

  • Muitas partes móveis: armazenamento, estado, redutores, criadores de ação, ações, ações assíncronas, middleware, componentes conectados
  • Bibliotecas. Para um aplicativo simples que se comunica com uma API REST, você precisa: redux, react-redux, redux-thunk (ou outros) + bibliotecas adicionais se você quiser testar coisas
  • Quantidade de lugares em que você deve colocar o código (consulte _ partes móveis_)

Eu acho que redux é uma ótima biblioteca que faz todo o sentido por si só e eu acho que ela tem ótimas abstrações e é superescalável quando usada corretamente. Também aprecio que redux pode ser usado com qualquer biblioteca de IU, mas acho que na maioria dos casos ele será usado com react.

Geralmente eu acredito que muita frustração vem de muitas partes móveis.

Aqui estão alguns pensamentos que tive. Tudo isso pode ser construído em cima do redux para que fique como está.

  • Fornece uma biblioteca como react redux que vem adicionalmente com suporte para ações assíncronas embutidas.
  • Muitas ações assíncronas estão se comunicando com uma API REST, portanto, forneça um middleware idiomático para isso
  • Escreva componentes inteligentes como componentes reais em vez de usar o Connect. Eles podem então renderizar componentes burros em seu método render
  • Prescreva um layout de arquivo escalonável para _componentes de contêiner_, _componentes inteligentes_, _componentes mudos_, _ criadores de ação_ e _redutores_.
  • Forneça um _redux-cli_ para gerar o código, por exemplo redux action loadUsers
  • Padronize em uma camada assíncrona como redux-saga ou redux-observable e inclua-o na documentação (seria bom ter _um_ lugar para consultar para a maioria dos assuntos de redux)
  • padrão para recursos de linguagem estendidos (por exemplo, decoradores (@connect)) ou TypeScript para tornar as coisas menos verbosas em particular mapStateToProps e mapDispatchToProps (mobx requer decoradores e a sintaxe é direta)

T

Concordo, redux-actions é um bom exemplo de algumas abstrações simples que removem o clichê.

Deixe-me perguntar isso: Create-React-App tem o pacote react-scripts , que tem configurações pré-construídas de Babel e Webpack, e vem com um monte de padrões sensíveis embutidos. Qual seria a aparência de um pacote redux-scripts ?

Eu concordo com alguns dos outros comentários (negativos) sobre redux-thunk . Eu não recomendaria para iniciantes (provavelmente não recomendaria mais nada):

  1. Parece mágica para começar.
  2. Realmente não tira tanta placa de boiler. Dado um processo assíncrono mais complexo, ter que pegar dispatch dos props e passá-lo acaba sendo apenas uma pequena parte do código.
  3. Isso resulta em criadores de ação que você não pode compor juntos em fluxos de trabalho maiores.
  4. Um último ponto que não consigo articular muito bem sobre tornar o estilo redux mais uma estrutura do que uma biblioteca: você confia na estrutura para chamar seu código, em vez de chamar a biblioteca.

Nós o usamos muito em um aplicativo React-Native e foi muito útil, mas tivemos problemas para compor ações juntos (pense em "carregar perfil após login bem-sucedido"), devido ao redux-thunk que os criadores de ação efetivamente retornaram void (ou seja, não tendo nada como uma promessa para usar para sequenciar a próxima ação).

Isso tende a encorajar as pessoas a pensar que "a única maneira de fazer qualquer coisa é dispatch imediatamente do manipulador de eventos / callback React". E como estávamos usando connect de react-redux e nos apoiando fortemente em mapDispatchToProps , tendíamos a esquecer que nossos manipuladores de eventos poderiam ser apenas funções simples.

(note que o aplicativo acima foi escrito principalmente no início do ano passado, e nós realmente não acompanhámos o que estava acontecendo no grande ecossistema Redux, então ele pode estar desatualizado).

@bodhi : sem sair _muito_ da tangente, eu discordo de algumas dessas conclusões. redux-thunk tem 11 linhas e há algumas explicações interessantes por aí, como "O que é um Thunk?" . Thunks _são_ combináveis ​​até _alguma_ extensão, e eu acho que geralmente é mais fácil dizer a alguém "escreva essas duas linhas de declarações de função, em seguida, faça suas chamadas AJAX e outras coisas aqui". Eu tenho uma postagem que discute algumas das várias vantagens e desvantagens de thunks (e, em certa medida, sagas) em Idiomático Redux: Reflexões sobre Thunks, Sagas, Abstração e Reutilização .

Eu concordo que seria necessário haver _alguma_ maneira "abençoada" ou "embutida" de lidar com os efeitos colaterais em alguma camada de abstração hipotética. Sagas e observáveis ​​são ótimos, _se_ você entende como usá-los. Só não sei se eles seriam apropriados, visto que um objetivo potencial aqui é fornecer um caminho fácil para aprender e usar o Redux.

Acho que usar redux-thunk não é apenas fazer algo de forma assíncrona, mas também fazer algo que depende do estado atual. Interface muito limpa e simples, e incentiva o uso de criadores de ação.

Bodhi: Talvez um pouco fora do assunto, mas pensei que talvez valesse a pena mencionar que o despacho não retorna vazio, ele retorna o resultado de sua função interna. Portanto, se você, por exemplo, retornar uma promessa, poderá facilmente encadear ações. Consulte a seção sobre composição no readme:
https://github.com/gaearon/redux-thunk/blob/master/README.md

Além disso, gostaria apenas de agradecer à comunidade por ter essa discussão aberta, muito interessante ouvir os pensamentos e ideias de todos.
Pessoalmente, aderindo às críticas até agora, mas tentando separar claramente "o que aconteceu" de "como o estado deve mudar". Vejo alguns casos em nosso código em que cometemos esse erro (usando ações para dizer aos redutores o que fazer, em vez de os redutores apenas reagirem ao que aconteceu), então seria bom ver alguma biblioteca que de alguma forma tornou isso mais difícil de fazer (não vendido em sagas ainda).

Em 19 de março de 2017, às 23:48, Bodhi [email protected] escreveu:

Eu concordo com alguns dos outros comentários (negativos) sobre redux-thunk. Eu não recomendaria para iniciantes (provavelmente não recomendaria mais nada):

Parece mágica para começar.
Realmente não tira tanta placa de boiler. Dado um processo assíncrono mais complexo, ter que obter o despacho dos props e passá-lo acaba sendo apenas uma pequena parte do código.
Isso resulta em criadores de ação que você não pode compor juntos em fluxos de trabalho maiores.
Um último ponto que não consigo articular muito bem sobre tornar o estilo redux mais uma estrutura do que uma biblioteca: você confia na estrutura para chamar seu código, em vez de chamar a biblioteca.
Nós o usamos intensamente em um aplicativo React-Native e foi muito útil, mas tivemos problemas para compor ações juntos (pense em "carregar perfil após login bem-sucedido"), devido aos criadores de ação redux-thunk efetivamente retornarem void (ou seja, tendo nada como uma promessa de usar para sequenciar a próxima ação).

Isso tende a encorajar as pessoas a pensar que "a única maneira de fazer qualquer coisa é despachar imediatamente do manipulador de eventos / callback React". E como estávamos usando connect from react-redux e nos baseando fortemente em mapDispatchToProps, tendíamos a esquecer que nossos manipuladores de eventos poderiam ser apenas funções simples.

(note que o aplicativo acima foi escrito principalmente no início do ano passado, e nós realmente não acompanhámos o que estava acontecendo no grande ecossistema Redux, então ele pode estar desatualizado).

-
Você está recebendo isto porque está inscrito neste tópico.
Responda a este e-mail diretamente, visualize-o no GitHub ou ignore a conversa.

(desculpe continuar a tangente, mas ...)

vale ressaltar que dispatch não retorna void, mas sim o resultado de sua função interna.

Huh, ótimo! Acho que nunca olhei muito atentamente a documentação antes de tentar encontrar outra maneira de resolver nossos problemas.

A única coisa mais valiosa que tornou o Redux muito mais fácil para mim é tratar as ações como eventos e não como comandos . Isso elimina completamente a luta para decidir como projetar ações e o que incluir nelas.

Os componentes não precisam saber como a interação do usuário deve afetar o estado, eles apenas informam ao mundo externo o que aconteceu dentro deles, por exemplo, "botão X clicado" . Ao usar ações como comandos, você efetivamente introduz uma ligação bidirecional entre o componente e o estado.

Os redutores não são vinculados aos componentes, eles representam o estado do aplicativo e não o estado do componente , e são a única parte que realmente sabe como o estado muda. Não há barreira cognitiva para lidar com uma única ação em vários redutores porque uma ação não é uma declaração "o que fazer com o estado" .

Isso também remove qualquer caso para despachar várias ações de forma síncrona.

Qualquer caso para despachar uma ação única de vários lugares também desaparece. Você pode manter os criadores de ação perto do componente, o que torna mais fácil rastrear o componente que despachou a ação.

Olhando o log de ação no DevTools, você pode ver um histórico completo do que aconteceu dentro do seu aplicativo e é fácil ver a fatia de estado concreto afetada pela ação. A história permanece a mais curta possível.

Esta abordagem baseada em puxar faz o fluxo de dados verdadeiramente one-way e pilhas naturalmente com bibliotecas de gerenciamento de efeito colateral como redux-saga ou redux-observable .

@aikoven, embora eu concorde totalmente com isso (definitivamente houve muita discussão no passado comparando redux a fonte de eventos), o que você faz com coisas como FETCH_USER , que é muito comum de se ver (e algo que precisa ser feito). Isso parece mais "semelhante a um comando" do que "semelhante a um evento".

@blocka Sempre há algum evento que resulta em uma solicitação de rede. A própria solicitação pode ser envolvida em ações FETCH_USER_STARTED e FETCH_USER_DONE / FETCH_USER_FAILED , que é como o resultado da solicitação termina no estado.

👍 por redux-actions

O que eu também gosto nele, além de apenas reduzir o clichê, é que parece uma extensão muito natural do redux. Para algo como jumpstate , sinto que a implementação está indo um pouco mais longe e agora terei que aprender duas coisas em vez de uma.

Portanto, meu ponto é, quaisquer plug-ins que adicionarmos para reduzir o boiler plate devem se parecer muito com o redux, embora um com uma API menos detalhada.

Muito do clichê é o mesmo clichê que você tem em qualquer ambiente. Quando você encontra duplicação, geralmente resolvemos com uma abstração customizada. Essas abstrações, muitas vezes, não são úteis fora do seu projeto atual e uma "bala de prata" simplesmente não pode existir. Os requisitos de cada projeto são diferentes.

Mesma coisa com redux. Se você acha que precisa de uma ação FETCH_X_STARTED , e um criador e redutor de ação fetchX() para lidar com isso, etc., sinta-se à vontade para fazer sua própria abstração!

Culpar o redux por boilerplate é como copiar e colar todo o seu código e, em seguida, culpar o javascript por ter muito boilerplate.

Acho que usar redux-thunk não é apenas fazer algo de forma assíncrona, mas também fazer algo que depende do estado atual. Interface muito limpa e simples, e incentiva o uso de criadores de ação.

Usar redux-thunk para código síncrono não é uma grande ideia e deve ser mencionado nos documentos.
Se você compor muitas funções juntas, não tem certeza de que o fluxo de despacho não depende da ordem, por isso é mais difícil de raciocinar e testar.

Parece-me melhor ter criadores de ações puras e simplesmente usar batching de ações para modificações de estado mais complexas. Dessa forma, você tem apenas funções puras para testar.

Recomendo esta postagem do blog para obter um melhor entendimento: http://blog.isquaredsoftware.com/2017/01/idiomatic-redux-thoughts-on-thunks-sagas-abstraction-and-reusability/

@Machiaweliczny obrigado pelo artigo. Acho que a questão para mim é mais sobre onde você acaba colocando sua lógica de negócios (conforme discutido em https://medium.com/@jeffbski/where -do-i-put-my-business-logic-in-a- react-redux-application-9253ef91ce1 # .3ce3hk7y0). Você não está dizendo que seu fluxo de despacho (thunk, épico, saga, seja o que for) nunca deve ter acesso ao estado atual do aplicativo, está?

@dfbaskin

Lembre-se de que Redux não é um desenvolvimento orientado a domínio. "Lógica de negócios" é uma preocupação muito confusa aqui, e é mais "qual assinatura de função do conceito se encaixa melhor na lógica que estou tentando implementar". Sua "lógica de negócios" é espalhada por seletores, redutores, criadores de ação e "orquestradores" (temos uma palavra melhor para isso ainda?) Dependendo do que você precisa.

O redutor, sendo (state, action) => state é onde geralmente deveria estar a "lógica que depende do estado". E com certeza, em coisas como a Arquitetura Elm, toda essa lógica está na função "atualizar" (o equivalente ao nosso redutor).

Infelizmente, no Redux, o redutor só pode lidar com lógica síncrona. Portanto, a "lógica de negócios" assíncrona que depende do estado precisa obtê-la do componente via envio (se o componente tiver essa informação, o que nem sempre é) ou por meio do conceito de orquestrador de sua escolha (thunk, sagas, épico), que têm acesso ao estado para isso.

Se não fosse pela limitação do redutor, não haveria necessidade. Você realmente vê quando as pessoas usam redux-saga ou redux-observable: suas ações / criadores de ações geralmente se tornam quase triviais (na maioria dos casos, mais ou menos alguma normalização ou formatação), e a saga / épico são quase "redutores alternativos" , nisso você agora tem outra coisa que tem acesso à ação e estado e retorna uma "coisa", e a complexidade do redutor real é diminuída como resultado. Redutores e orquestradores estão intimamente relacionados (às vezes muito próximos, e não é ótimo ter 2 construções que são intercambiáveis ​​na metade do tempo ... mas é o que temos, podemos muito bem aproveitá-lo)

@Machiaweliczny : como autor daquele post "Pensamentos sobre Thunks", posso garantir que "evite usar thunks para trabalho síncrono" é o _oposto_ do que eu estava tentando dizer :)

Mais uma boa discussão, mas estamos começando a nos afastar um pouco do assunto. (Isso é uma bicicleta que eu vejo ali? :))

Deixe-me apontar de volta às perguntas originais:

  • Como seria o uso idiomático do Redux com "menos padrão"? Como podemos fornecer soluções para essas reclamações?
  • Quais abstrações possíveis poderiam ser criadas para simplificar o processo de aprendizado e uso, mas sem realmente ocultar o Redux (e, com sorte, forneceria um caminho de migração / aprendizado para o Redux "básico")?
  • Quanto disso poderia ser resolvido com documentos aprimorados de alguma forma?

Que passos concretos podemos implementar para lidar com isso?

No reino das etapas incontestáveis, acionáveis ​​e de curto prazo, eu diria:

1) Facilite a configuração da loja (talvez com uma configuração padrão? Não sei se esse ainda é o caso, mas Elm costumava ter um tipo de "aplicativo inicial" e um tipo de aplicativo normal. O aplicativo inicial foi usado para aplicativos simples e em material de treinamento para cobrir 90% dos casos em que as pessoas estão apenas aprendendo. Até hoje, admito que não posso configurar a loja Redux com middlewares básicos (devtools, thunks) sem procurar as assinaturas no documento. Eu não acho que muitas pessoas argumentariam que os recém-chegados precisam saber como configurar os middlewares de uma loja para aprender os conceitos básicos do Redux.

2) Este já pode ser o caso, certifique-se de adicionar Redux com a "loja inicial" acima para criar-reagir-app é o mais fácil possível, para que um recém-chegado possa ter um aplicativo Redux instalado e rodando em 2 minutos.

Acho que isso nos levaria muito, muito longe.

Edit: por starter app, não quero dizer um boilerplate do app, mas sim um "createStore" que não pode ser configurado, mas tem padrões razoáveis ​​que as pessoas podem apenas importar e terminar com ele. Em seguida, eles podem simplesmente passar para a createStore "real" quando a superarem.

Parece um conceito fantástico aqui.

Na segunda-feira, 20 de março de 2017 às 10h02, Francois Ward [email protected]
escreveu:

No reino das etapas incontestáveis, acionáveis ​​e de curto prazo, eu diria:

1

Torne a loja mais fácil de configurar (talvez com um padrão
configuração? Não sei se este ainda é o caso, mas Elm costumava ter
um tipo de "aplicativo inicial" e um tipo de aplicativo normal. O aplicativo inicial foi usado para
aplicativos simples e em material de treinamento para cobrir 90% dos casos em que as pessoas estão
apenas aprendendo. Até hoje, admito que não consigo configurar a loja Redux
com middlewares básicos (devtools, thunks) sem consultar o documento para
as assinaturas. Eu não acho que muitas pessoas diriam que os recém-chegados precisam
saber como configurar os middlewares de uma loja para aprender o núcleo do Redux
conceitos.
2

Este pode já ser o caso, certifique-se de adicionar Redux com o acima
"loja inicial" para criar-reagir-app é o mais fácil possível, então um novato
pode ter um aplicativo Redux instalado e funcionando em 2 minutos.

Acho que isso nos levaria muito, muito longe.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/reactjs/redux/issues/2295#issuecomment-287806663 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AFUmCQYkUwjkCugevDBWC8TOu0HhWJTnks5rnqMWgaJpZM4MhnVF
.

Nossos módulos usam combineReducers para que cada fatia de estado em um módulo tenha um redutor dedicado para ele (acredito que essa abordagem seja descrita na seção Redutores de estruturação dos documentos, também conhecidos como "redutores de fatia"). Isso torna as coisas mais fáceis de raciocinar porque as instruções switch são muito menores. Também permitiu que redutores comuns surgissem em nossa base de código. Os redutores mais simples eram idênticos em todos os módulos, exceto por seus tipos de ação, então fomos capazes de reduzir o clichê por ter funções auxiliares (fábricas de redutor?) Que tornam esses redutores para nós por tipo de ação:

const { makeIndicator, makePayloadAssignor } from '../shared/reducers';

const searchModule = combineReducers({
  searching: makeIndicator(c.SEARCH),
  results: makePayloadAssignor(c.SEARCH_RESPONSE, [])
});

Talvez identificar redutores de fatia mais comuns como este seja uma boa maneira de aliviar as preocupações do clichê, onde eles poderiam servir como blocos de construção primitivos para nossos redutores.

Esta é a refatoração básica de javascript. Como eu disse antes ... "javascript" tem um
muito "boilerplate", até que você aplique coisas como abstração ao seu código.

Redux é apenas javascript. Não há nada de mágico nisso.

Na segunda-feira, 20 de março de 2017 às 12h44, Markus Coetzee [email protected]
escreveu:

Nossos módulos usam combineReducers para que cada fatia de estado em um
módulo tem um redutor dedicado para ele (acredito que esta abordagem está delineada
na seção de Redutores de Estruturação do documento, também conhecido como "fatia
redutores "). Isso facilita o raciocínio, porque a mudança
as declarações são muito menores. Também permitiu que redutores comuns surgissem
em nossa base de código. Os redutores mais simples eram idênticos em todos os módulos
exceto por seus tipos de ação, então fomos capazes de reduzir o clichê em
tendo funções auxiliares (fábricas de redutores?) que torna esses redutores para
nós por tipo de ação:

const {makeIndicator, makePayloadAssignor} de '../shared/reducers';
const searchModule = combineReducers ({
pesquisando: makeIndicator (c.SEARCH),
resultados: makePayloadAssignor (c.SEARCH_RESPONSE, [])
});

Talvez identificar redutores de fatia mais comuns como este seja uma boa
maneira de aliviar as preocupações clichê, onde eles poderiam servir como
blocos de construção primitivos para nossos redutores.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/reactjs/redux/issues/2295#issuecomment-287820595 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AACourLpL5--NJiRzrWmKFJ31cl5DXJrks5rnqzxgaJpZM4MhnVF
.

Eu concordo com a maioria dos comentadores que disseram que é melhor explicar os padrões redux comuns do que desenvolver algum redutor clichê. Meus colegas de equipe e eu começamos a trabalhar com redux há 1,5 anos e estávamos confusos sobre as coisas mais simples: que redux é principalmente fonte de eventos, que a mesma ação pode ser controlada por vários redutores, que ação pode conter toda entidade de negócios não apenas seu id , que os redutores são apenas funções e você é livre para fazer o que quiser com eles - compor, gerar, dividir, etc. Cometemos erros comuns - usamos ações como comandos remotos e nos perguntamos por que simplesmente não usar a chamada de método clássica; criou middlewares enormes e evitou a saga redux porque "generators é muito complicado" (embora a saga redux seja excelente!), fez arquivos longos com switches enormes. É claro que isso se deve às habilidades de programação medíocres, mas também à falta de informações estruturadas. Hoje a documentação está muito melhor, muito obrigado aos mantenedores!

Este é um tópico muito valioso no Redux como uma biblioteca.

Esta é a refatoração básica de javascript. Como eu disse antes ... "javascript" tem um
muito "boilerplate", até que você aplique coisas como abstração ao seu código.
Redux é apenas javascript. Não há nada de mágico nisso.

Perfeito, @blocka! Acho que essa mensagem precisa ser espalhada.

Redux está parecendo incomum e clichê para as pessoas por causa de sua abordagem mínima. Minimal parece estranho para um "framework" em geral (código mínimo, princípios mínimos).

Algumas pessoas estão acostumadas a escrever código "framework-y" em vez de escrever o próprio JavaScript. Quando os desenvolvedores usam uma estrutura, a maneira integrada de fazer as coisas é implicitamente esperada. Triste como o inferno, mas é verdade.

Acredito que o Redux está ficando mais fácil de começar do que nunca, mas ainda precisamos deixar claro para as pessoas que não esperavam que o Redux fizesse tudo. @gaearon diz isso claramente o tempo todo, mas infelizmente as pessoas estão acostumadas com frameworks fazendo de tudo. Por que eles deveriam se motivar a aprender algo que "não faz muito"? O Angular faz muito mais do que o Redux. Por que Redux? A resposta é provavelmente evidente para todos nós nesta edição. Mas está claro para iniciantes?

Eu escrevi um pequeno artigo sobre isso ontem: Não culpe React ou Redux . Claro que posso estar errado em tudo isso.

Existe um precedente para ter camadas de abstração no topo de uma biblioteca avançada. Recentemente, o Tensorflow trouxe Keras como uma abstração no topo da API principal: http://www.fast.ai/2017/01/03/keras/.

Usar o TensorFlow me faz sentir que não sou inteligente o suficiente para usar o TensorFlow; ao passo que usar Keras me faz sentir que as redes neurais são mais fáceis do que eu imaginava. Isso ocorre porque a API do TensorFlow é prolixa e confusa e porque Keras tem a API mais bem projetada e expressiva que já experimentei. Eu estava com vergonha de criticar publicamente o TensorFlow depois de minhas primeiras interações frustrantes com ele. Parecia tão desajeitado e antinatural, mas certamente essa foi a minha falha.

Eu sinto que é uma experiência semelhante para a maioria dos novatos que vêm para o Redux. Substitua Tensorflow por Redux e Keras por Jumpstate . Redux é muito poderoso, mas a maioria dos usuários provavelmente não precisa de todo o controle disponível. Mais do que provavelmente, eles estão vindo do Angular ou aprendendo React + Redux em um bootcamp ou assistindo a vários tutoriais. Embora o Redux não precise ser simplificado para novos usuários, também não é um antipadrão para fornecer uma abstração mais fácil que provavelmente pode cobrir 80% dos casos de uso em potencial.

Pessoal, se redux estivesse bem do jeito que está, não estaríamos tendo essa conversa. Independentemente de o redux ser útil ou estruturalmente sólido, as pessoas ainda se sentem "mal" quando o aprendem pela primeira vez. Esses sentimentos são válidos.

As pessoas que comentam neste tópico são todos especialistas em redux - é claro que estamos felizes com redux; internalizamos sua filosofia e nos sentimos confortáveis ​​fazendo nossas próprias abstrações para gerenciar "clichês". Não somos o público que este tópico pretende servir. Precisamos ter alguma empatia com os usuários que estão chegando ao redux pela primeira vez, talvez até mesmo chegando à programação funcional pela primeira vez.

Por exemplo: aqui está uma reclamação que ouço frequentemente sobre redux (que eu não acho que tenha sido mencionada em upthread): não é suficiente apenas usar redux, você também "precisa" usar react-redux, redux-thunk, redux-actions, etc. .

Você literalmente precisa usar todos esses outros pacotes para usar o redux? Não.
A maioria dos usuários redux acabará usando alguns ou todos esses pacotes adicionais? sim.

O número de pacotes em package.json importa? Não, na verdade não.
O número de pacotes em package.json afeta a maneira como as pessoas se sentem? Absolutamente.

Agora, eu acho que é justo acreditar que o redux deve permanecer como está, e outro pacote ( create-redux-app ou qualquer outra coisa) deve lidar com a montagem deles. Mas temos um problema real de complexidade em nossas mãos e não é suficiente dizer aos usuários para RTFM.

Independentemente de o redux ser útil ou estruturalmente sólido, as pessoas ainda se sentem "mal" quando o aprendem pela primeira vez. Esses sentimentos são válidos

Absolutamente. Mas nem todas as pessoas se sentem assim. Alguns fazem. Lembre-se de que você nunca ouvirá falar de pessoas que não tiveram problemas. Você só vê aqueles que fazem perguntas ou clicam em stackoverflow / reactiflux. Dos que nunca o fazem, alguns também precisam de ajuda, mas não sabem como pedir ... e alguns estão bem também, e você não quer piorar as coisas para eles ... do contrário, eles ficarão seja aquele que vem aos fóruns e isso terá um ganho líquido zero.

Redux não se tornou popular sem motivo. Muitas pessoas acharam que era muito bom e recomendaram a outras pessoas :)

Agora, eu acho que é justo acreditar que redux deve permanecer como está, e outro pacote (create-redux-app ou qualquer outro) deve lidar com a montagem deles.

Eu gostei dessa ideia. Seria possível argumentar que os boilerplates existentes já resolvem isso, mas o React também tinha muitos clichês na época em que as pessoas reclamaram de serem sobrecarregadas com ferramentas ao tentar entrar no React. create-react-app foi uma ótima resposta para tudo isso, porque eliminou muitos passos para iniciantes já entrarem no React _próprio_.

Mas ainda é clichê sob o capô. Portanto, ainda precisamos encorajar as pessoas a comprarem o ecoystem e deixar claro que o Redux em si não faz muito por design . Não é possível fugir do ecossistema se você quiser usar React ou Redux.

Não acredito que incluir pacotes como redux-thunk no núcleo do Redux seja o caminho a percorrer aqui.

Apenas para maior clareza, o tipo de ideia que estou lançando não é sobre incluir as coisas diretamente no núcleo. Eles são sobre a criação hipotética de algum tipo de "configuração pré-construída" ou "camada de abstração fácil de usar" que seria um pacote separado ou ferramenta CLI ou algo assim, mais na linha de create-react-app .

Acho que é melhor eu intervir como autor de Jumpstate / Jumpsuit.

TL; DR:
Redux é difícil de aprender e de configurar / integrar porque é de baixo nível. A comunidade poderia se beneficiar de uma API redux padronizada de nível superior voltada para o caso de uso de 90% para facilitar a curva de aprendizado e até mesmo operar como uma solução para projetos mais simples. A Jumpstate está tentando resolver isso, mas não é uma solução de longo prazo. Precisamos começar a propor ideias possíveis (real ou metocódigo) sobre como essa API poderia ser.


Redux é muito difícil de aprender desde o início e, muitas vezes, tão difícil de integrar com novos conceitos como lógica assíncrona, efeitos colaterais, middleware personalizado, etc. era muito novo para o ecossistema de reação.

Após alguns dias de aprendizagem, fui imediatamente recomendado para aprender a redux. Essa recomendação veio de desenvolvedores muito experientes e novatos que haviam feito (ou estavam fazendo) o mesmo. Ele estava sendo saudado como a solução de fato para qualquer coisa que se estendesse além de setState (vamos deixar setState gate fora disso 😉). Tudo isso por um bom motivo, porque redux é incrível.

Eu inevitavelmente atingi a curva de aprendizado e ao buscar ajuda imediatamente percebi que o marketing e a abordagem documentada para redux assumiram um tom de "Redux é difícil, os conceitos são de baixo nível, a API está travada e você só precisa avançar isto."

Então foi isso que fiz junto com todos os meus colegas. Nós impulsionamos porque foi o que fomos educados para fazer. Ao longo dessa jornada, entretanto, me atrevi a criar uma camada de abstração muito cedo que iria temporariamente e deliberadamente esconder parte da complexidade e recursos avançados que o redux tinha a oferecer.

Eu não precisava de criadores de ações personalizadas, não queria me preocupar com mapeamento de ações e despachantes para componentes e, como muitos outros, optei por um layout de redutor menos prolixo no lugar de uma instrução switch.

Funcionou fantasticamente. Tão bem, na verdade, que acelerou o processo de redux de aprendizagem para o resto dos meus colegas e outros desenvolvedores que estavam lutando da mesma forma com a curva de aprendizagem.

Nós o projetamos de forma que o redux avançado ou "idiomático" ainda pudesse ser usado quando necessário, mas realmente o projetamos para nosso caso de uso de 90%.

De forma alguma estou dizendo que o jumpstate cobre todas as bases, na verdade, ainda há tantas coisas que precisam ser alteradas para que o jumpstate se comporte "idiomicamente" (criadores de ações personalizáveis, removendo importações de ações globais ... há muito) , mas definitivamente ajudou muitas pessoas a aprender o básico e lhes deu um caminho para entender como o redux funciona em um nível muito simples. Sempre recebo mensagens na Slack org do Jumpstate dizendo que o jumpstate ajudou alguém a reduxar.

Se essas pessoas ainda estão usando o jumpstate hoje ou não, não importa muito (mas muitas pessoas ainda estão usando a produção hoje). O que importa é a experiência que tiveram e com que rapidez foram capazes de se tornar produtivos no ecossistema redux.

Mais algumas ideias que vêm à mente para esta discussão:

  • proponha meta exemplos de como um redux simplificado pode parecer, apenas dê uma tentativa!
  • discutir os requisitos e decidir sobre um padrão para os redux middlewars frequentemente duplicados e extremamente opinativos. Poderíamos começar com tratamento assíncrono. Isso poderia resolver tanta fragmentação na comunidade redux e ajudar os esforços de todos fazer a diferença para a sobrevivência a longo prazo e o uso de redux.

Quanto disso poderia ser resolvido com documentos aprimorados de alguma forma?

Bastante. Quando se trata da documentação do Redux, sinto em muitos graus que é pior do que a documentação do AngularJS 1 porque, como a do AngularJS, é desnecessariamente detalhada, mas, ao contrário do AngularJS, falha no princípio "mostre, não diga".

Os documentos do Redux preferem trechos de código ao invés de demonstração real do código, o que significa que há muitos momentos "aqui está um conjunto de código; não vamos dizer como ele se conecta, mas acredite que funciona". A falta de capacidade de executar exemplos em um navegador significa que o usuário é forçado a confiar em seus próprios instintos de que o que está fazendo localmente funciona e, se algo não funcionar, ele está sozinho. Mesmo o aplicativo de lista de tarefas simples, acho que dificilmente é o melhor exemplo de "hello world" de Redux - poderia ser muito mais simples.

Os diagramas certamente ajudariam aqui. Por exemplo, eu gosto do @sunjay ; um que pode ser ainda melhor é projetar um para o exemplo da Lista de Tarefas em si - como os arquivos são conectados, etc. de uma visão de alto nível. As imagens quase sempre são melhores para transmitir textos longos e podem ajudar a reduzir o detalhamento dos documentos. As imagens também ajudariam os iniciantes a manter o foco e entender melhor o Redux como um todo.

Meus dois centavos: por favor, não troque o núcleo. Seu brilho está em sua simplicidade. Nesse ponto, adicionar algo provavelmente prejudicaria o todo.

A facilidade de uso e outras abstrações podem acontecer no ambiente do usuário. Também não sinto que seja necessário haver uma forma oficial ou idiomática de usá-lo. É um contêiner de estado previsível, é isso!

Pode ficar por conta própria, vamos ser ❤️

Dito isso, com certeza, empacote-o como quiser, criando mais bibliotecas opinativas sobre ele. Isso é o que eu também faço, mas não vamos mudar o núcleo, por favor.

@HenrikJoreteg , não tenha medo! Tenho quase certeza de que nada do que discutirmos aqui mudará o núcleo. O núcleo é completo e independente. :)

Bastante. Quando se trata da documentação do Redux, sinto em muitos graus que é pior do que a documentação do AngularJS 1 porque, como a do AngularJS, é desnecessariamente detalhada, mas, ao contrário do AngularJS, falha no princípio "mostre, não diga".

Isso é verdade. Uma coisa quando Redux era novo é que o médico era esparso, mas o básico estava lá. Muitas pessoas o adotaram porque era "tão simples". Mas os recursos online agora estão tentando mostrar "técnicas do mundo real", que muitas vezes são apenas "meu middleware favorito" e "meu ferramental de redução de clichê favorito". As pessoas ficam sobrecarregadas.

Há algo a ser dito sobre "menos é mais"

@Phoenixmatrix , @Sylphony : então, como seria uma possível reformulação de documentos?

Pessoalmente, para combiná-lo com minhas sugestões acima de ter uma "loja inicial", eu o dividiria em dois (não 2 sites / documentos diferentes, mas 2 seções diferentes).

A "arquitetura Redux", que teria muitos desenhos bonitos e simples, explica ações e redutores, introduz react-redux e talvez thunks, usa a "loja inicial" para limitar qualquer tipo de configuração inicial e mostra como isso pode ser fácil ser para fazer um aplicativo simples que faz algumas solicitações ajax e renderiza coisas na tela.

Todo o resto pode ir para uma seção "explorar" com os conceitos mais avançados. Mesmo assim, provavelmente arrancaria muitas coisas. Alguém me disse hoje que há uma seção sobre como ter várias lojas em um aplicativo. É bom saber, mas os usos para isso são muito avançados. Não acho que nenhum recém-chegado precise tropeçar nele sem olhar.

Documentos melhores são sempre uma ótima ideia, mas não acho que isso resolve o problema central aqui. Bibliotecas de abstração estão sendo escritas e adotadas devido ao clichê e ao detalhamento da API Redux. Essas mesmas bibliotecas estão fragmentando a comunidade Redux porque são obviamente necessárias em algum nível ou outro. É frustrante quando os mesmos autores que estão ativamente tentando contribuir para o ecossistema são reprimidos e rejeitados publicamente porque "não entendem o Redux". Se a comunidade puder, em vez disso, criar uma abstração mais simples, não parte do núcleo do React, mas "abençoada" em algum grau, então todos ganham. Usuários hardcore continuam usando Redux como está, outras pessoas podem usar uma abstração com uma API mais fácil / menos detalhada.

@derekperkins Como chegamos a um consenso sobre uma biblioteca "abençoada"? Como decidimos o que vai nele e quem vai trabalhar nisso?

Sou totalmente a favor de algo assim, mas como podemos evitar apenas criar outra biblioteca que apenas algumas pessoas usam e, assim, fragmentar o ecossistema ainda mais?

Xkcd relevante: https://xkcd.com/927/

Sim, redux's core e react-redux são o mais próximo de um consenso que se pode chegar. Mesmo redux-thunk e redux-actions são bastante limítrofes, porque mesmo nesse nível a maioria das pessoas tem necessidades diferentes.

Reduzir o clichê no Redux é uma questão de "eu não precisoentão vou abstrair isso. Mas mesmo para os recém-chegados, "essa parte" varia dramaticamente.

Caramba, temos muitos (várias dezenas) aplicativos redux em funcionamento e é difícil construir uma pilha de redução padrão comum porque aplicativos diferentes têm requisitos diferentes. É fácil quando você tem um único aplicativo ou alguns com os mesmos requisitos. Mesmo os pequenos diferem um pouco.

A ideia aqui não é montar um kit de ferramentas que resolva todos os problemas para todas as pessoas. Usando o CRA como exemplo: há várias maneiras de configurar o Babel, o Webpack e o ESLint. O que o CRA oferece é uma maneira única e opinativa de fazer com que todos funcionem sem qualquer incômodo por parte do usuário, e escolhe deliberadamente uma série de configurações que tornam as coisas melhores para os alunos. Em seguida, permite que o usuário assuma o controle da configuração _se quiser_.

Ele também não tenta resolver todos os casos de uso. O CRA não tenta lidar com a divisão de código avançada, vários pontos de entrada, SSR ou coisas assim. Os documentos do CRA _do_ apontam para outras ferramentas e opções que podem oferecer mais configurabilidade e funcionar melhor para certos casos de uso.

Essa é uma ótima maneira de colocar isso. Algo para começar a funcionar rápido que
envolve apenas a instalação de redux e esta camada de configuração hipotética? Este
seria fantástico.

Outra ideia que tive seria um sinalizador que você poderia definir no modo de desenvolvimento que poderia
observe e exponha oportunidades de aprendizagem incrementais para o usuário. No
desta forma, a camada de abstração pode servir como uma ferramenta de ensino interativa.
Na segunda-feira, 20 de março de 2017 às 16:14 Mark Erikson [email protected]
escreveu:

A ideia aqui não é montar um kit de ferramentas que resolva todos os problemas
para todas as pessoas. Usando o CRA como exemplo: há várias maneiras de configurar
Babel e Webpack e ESLint. O que o CRA faz é oferecer um único e opinativo
maneira de fazer com que todos funcionem sem qualquer incômodo por parte do usuário, e
escolhe deliberadamente uma série de configurações que tornam as coisas melhores para
aprendizes. Em seguida, permite que o usuário assuma o controle da configuração seeles querem .

Ele também não tenta resolver todos os casos de uso. CRA não tenta
lidar com divisão de código avançada, vários pontos de entrada, SSR ou coisas como
naquela. Os documentos do CRA apontam para outras ferramentas e opções que podem oferecer
mais configurabilidade e funcionam melhor para determinados casos de uso.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/reactjs/redux/issues/2295#issuecomment-287914805 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AFUmCactFzsw7etmGGP8MFK6kfNaOzTJks5rnvorgaJpZM4MhnVF
.

@sunjay Eu sabia qual link xkcd era mesmo sem precisar clicar. :)

Estou de acordo com @markerikson. Esta não é uma tentativa de lidar com todos os casos extremos para cada pessoa. É uma declaração opinativa dos principais desenvolvedores do Redux dizendo, "esta é uma boa maneira de fazer as coisas funcionarem". Existem padrões lógicos que podem ser substituídos se necessário, mas eu apostaria que os padrões funcionarão para 80% dos desenvolvedores.

Isso pode ou não ser escrito no núcleo do Redux. Ainda acho que há um lugar para algo como o Jumpstate que faz mais do que acelerar a curva de aprendizado.

A curva de aprendizado do Redux pode ser íngreme, mas uma vez que você entende os conceitos, a necessidade de camadas de abstração geralmente desaparece

Acho que isso é verdade até certo ponto, mas não significa necessariamente que você sempre queira eliminar a camada de abstração. Embora eu tenha escrito C no passado e entenda a alocação de memória, prefiro muito mais escrever em Go, onde a coleta de lixo é tratada para mim. De acordo com meu exemplo do Tensorflow anterior, seria mais eficiente gravar nas apis de nível inferior, mas também há muito a ser dito sobre a facilidade de uso da abstração Python keras. Da mesma forma, para Redux vs Jumpstate (ou qualquer abstração que venha deste problema), não é que o clichê não seja necessariamente difícil de escrever, é apenas complicado para a maioria dos casos de uso que não precisam de toda a flexibilidade do Redux bruto.

Se dependesse de mim, gostaria de ver isto:

  • Um subconjunto amigável de Flow / TypeScript que é mais fácil de digitar do que o Vanilla Redux.
  • Não enfatizar muito as constantes (apenas torne o uso de literais de string mais seguro).
  • Manter a independência do React ou de outras bibliotecas de visualização, mas tornando mais fácil usar os vínculos existentes (por exemplo, fornecendo mapStateToProps implementações).
  • Preservando os princípios do Redux (ações serializáveis, viagem no tempo e recarregamento a quente devem funcionar, o log de ação deve fazer sentido).
  • Oferecer suporte à divisão de código de uma maneira mais direta e pronta para uso.
  • Incentivando a colocação de redutores com seletores e tornando-os menos difíceis de escrever juntos (pense em pacotes de seletores de redutor que são fáceis de escrever e compor).
  • Em vez de colocar criadores de ação com redutores, livrar-se completamente dos criadores de ação e tornar natural o mapeamento de muitos para muitos de ações para redutores (em vez de fugir disso como a maioria das bibliotecas).
  • Tornar padrões de desempenho razoáveis ​​para que a memorização por meio de Selecionar novamente “simplesmente funcione” para casos de uso comuns, sem que os usuários escrevam esse código.
  • Contendo auxiliares integrados para indexação, normalização, coleções e atualizações otimistas.
  • Tendo suporte de fluxo assíncrono testável integrado.

Acima de tudo, é claro, embora não haja problema em marcá-lo como uma coisa oficial do Redux.
Além disso, não vou escrever isso. Mas você pode.

Para mim, há alguns meses, quando aprendi redux , li o documento, mas não entendo muito bem, então passei 2 dias lendo o código src e , em seguida, todas as descrições sobre api de o doc ficou claro .

E então, o pensamento sobre o "design de estado", "divisão de redutor", "design de middleware", "solução assíncrona" ...... capítulos tornam-se claros também com o desenvolvimento do projeto nos próximos meses.

Então, eu acho que ler o código src é o primeiro passo para aprender redux , e somente depois disso, você pode entender e explorar o ambiente de redux mais suave.

suporte assíncrono por padrão.

Não há necessidade de usar outro plugin como redux-thunk, redux-saga .

suporte assíncrono por padrão

Sim, é só que as pessoas olham para ele por 0,5 segundo antes de procurar algo melhor. Nada o impede de chamar APIs dentro de seus componentes e, em seguida, chamar dispatch nas resoluções de retorno de chamada / promessa. É que as pessoas querem externá-lo imediatamente (eu incluído). Mas você pode fazer o assíncrono muito bem, sem nenhum middleware.

O comentário de @gaearon é perfeito, pois destaca o quão ampla é a varredura. Eu amo e aprecio totalmente a precisão e elegância e poder do Redux 2.0 que ele propõe, mas quase nenhuma dessas melhorias é relevante para mim!

Na verdade, acho isso fascinante.

Minha própria biblioteca de abstração Redux faz quase inteiramente o oposto. Acho imenso valor em ações de redutor único, em agrupar funções de redutor atômico com seus códigos de ação e seletores, em matar strings inteiramente em favor de chaves de objeto. É minha própria solução de 90%, mais semelhante ao CRA em atitude do que qualquer outra coisa.

O ponto interessante é muito sobre: ​​que problemas estamos tentando resolver? Existem muitos problemas, com vários espaços de solução diferentes disponíveis. Se Dan construísse Redux 2.0 da maneira que ele descreveu, eu reconstruiria minha própria biblioteca de abstração em cima disso também!

@jbellsey Redux é ótimo em fornecer ações e estado para aplicativo globalmente - mas em escopo definido - você pode ter instâncias infinitas de armazenamento redux, mas você pode combiná-los. Basicamente, isso é útil para bibliotecas. Se você vir uma biblioteca falando sobre redux dentro, você pode se beneficiar com ...

que problemas estamos tentando resolver?

Estado global do aplicativo. R eliable um sthetics E D L elivered nified e X tensible: coração;

Ninguém quer globais. Mas todo mundo precisa de um: tm:

Por favor, mantenha o redux simples como está agora. É um padrão. Os livros de receitas sempre surgirão em torno de: 100:

@markerikson Seria uma boa ideia começar um documento / planilha para organizar esses pensamentos? Já surgiram algumas ideias incríveis e só se passaram 48 horas 🎉

Para mim, eu não recomendaria às pessoas usar thunks ou sagas. Em vez disso, aprenda técnicas de injeção de dependência em JavaScript.

Redux fica mais fácil quando eu o trato como um banco de dados simples:

  • Eu digo ao Redux o estado inicial e como uma ação (evento) afeta o estado do aplicativo. (Como esquema de banco de dados e procedimentos armazenados.)
  • Em seguida, o Redux se encarrega de gerenciá-lo e notificar os ouvintes, e fornece maneiras de inspecionar e depurar o estado.

Para mim, isso é tudo que o Redux é para mim (eu não esperaria que um banco de dados fizesse uma chamada HTTP). Para I / O e coisas assíncronas, eu executo fora do Redux. Isso mantém minha loja Redux previsível. A assinatura de tipo é sempre store.dispatch(actionObject) . Nenhuma função de despacho e nenhum significado oculto dentro da ação (por exemplo, despachar uma ação não fará uma chamada de API).

@tannerlinsley : Sim, vá em frente.

Uma desvantagem para eu começar esta discussão: já tenho uma tonelada de coisas que preciso trabalhar e sobre as quais escrever. Muito disso é autoimposto, mas significa que não tenho tempo suficiente para trabalhar em alguns dos tópicos relacionados ao Redux que gostaria de investigar, muito menos lidar com coisas como uma grande reformulação de documentos ou construir um novo kit de ferramentas coçar, arranhão.

Eu absolutamente quero me envolver nesses esforços possíveis, mas vai precisar que outras pessoas se juntem e trabalhem juntas. (Últimas palavras famosas de todos os mantenedores de OSS ... :))

Redux fica mais fácil quando eu o trato como um banco de dados simples

Isso é o que eu recomendo!

  • Mantenha sua loja normalizada
  • Você pode preparar visualizações como dados. Faça isso por redutores dedicados - você não precisa de reselect . Considerar.
  • As ações não devem desencadear outras ações - isso pode parecer fácil. Mas é difícil se você tiver ganchos componentDidMount . Não sei como resolver isso. Mudar isso na hierarquia nem sempre é fácil

FWIW, estou usando Redux com D3.js (sem React) e está indo muito bem. Alguns exemplos disso estão listados no componente d3 .

A coisa que eu mais sinto falta nas ligações React Redux é connect . O ponto que eu estaria mais interessado no esboço / visão acima de @gaearon é "fornecer mapStateToProps implementações".

Você pode preparar visualizações como dados. Faça isso por redutores dedicados - você não precisa selecionar novamente. Considerar.

Sim, isso é meio que o Twitter faz em sua loja, pelo menos eu acho que sim - eles têm entities branch que contém ids regulares para mapas de dados e por exemplo timeline view que é basicamente o feed principal de você veja qual contém referências de id para o branch de entidades, mas já está pré-computado.

E é isso que estou buscando nos próximos refatores, já que selecionar novamente listas altamente dinâmicas não é ... muito bom;) a única desvantagem que vejo é que você meio que acaba com dados duplicados e também manipulando atualizações e exclusões na visualização pode ser bastante complicado no longo prazo, pois você precisa se lembrar frequentemente de cerca de 2 lugares (ou mais).

@stefensuhat quando tentei implementar o Redux por conta própria, usei um loop Promise para tornar as ações assíncronas possíveis. Você pode conferir em https://github.com/iddan/delux

@gaearon concorda totalmente com sua lista! Estamos trabalhando em um boilerplate redux seguindo 90% da lista da organização em que estou trabalhando (também, seguindo os princípios dos patos). É um lançamento antecipado no momento, não está pronto para publicação.

Eu definitivamente gostaria de contribuir para essa boa ideia!

@markerikson @tannerlinsley

Quanto à organização dessas ideias, sugiro que, depois de fazer a planilha, você crie os problemas do Github nos repositórios apropriados para acompanhar o desenvolvimento. Você deve, então, comentar aqui com uma lista dessas questões.

Isso não garante que algo em particular será enviado com redux, mas dá às pessoas interessadas naquele assunto em particular a oportunidade de acompanhar a discussão e trabalhar em conjunto para que isso aconteça.

A responsabilidade de transformar essas sugestões em realidade recai sobre todos nós que estamos interessados ​​em cada novo recurso ou abordagem. Embora Mark tenha iniciado a discussão, tenho certeza de que ninguém espera que ele vá e implemente tudo. :)

Sim, a lista de @gaearon é ideal, mas como algumas pessoas já mencionaram, isso é um monte de coisas. Qualquer um que tentar enfrentá-lo de forma direta enfrentará a queda das bicicletas até o esquecimento. Adoraria ver isso acontecer de qualquer maneira, mas acho que peças menores devem ser atacadas por vez, em vez de construir uma camada completa no topo (novamente empurrando meu exemplo de uma loja inicial pré-configurada;))

Dito isso, quando / se alguém tentar atacar toda a lista, lembre-se também de que outras ferramentas e frameworks existem fora do Redux, e até mesmo fora do React. React / Redux tem um conjunto interessante de benefícios sobre o vanilla Flux, sobre MobX, sobre VueJS e seu ecossistema sobre Angular. O que quer que a comunidade faça, ela provavelmente deseja manter o foco em alguns desses benefícios (alguns dos quais fazem parte da lista de

Exemplo que estou inventando: pode ser tentador fazer um módulo que permite fazer uma função que atualiza automaticamente um redutor gerado automaticamente. Mas, depois de fazer isso, você replicou o MobX, de modo que não é muito útil fazer.

@Phoenixmatrix sim, o que quero dizer é que redux tem middleware padrão, então não precisamos usar um externo. 😄

Eu realmente não vejo nada de errado com a implementação atual do Redux. O clichê existe, mas não é grande coisa se você tiver um sistema de tipos.

Um grande problema para mim é que as pessoas parecem não entender que estamos construindo aplicativos de front-end que são muito mais complexos do que costumavam ser alguns anos atrás. Se estamos construindo aplicativos maiores, mais complexos, com equipes grandes, é normal para mim que a dificuldade aumente significativamente, que surjam novos padrões, mas as pessoas rejeitam essa dificuldade.

Não estou dizendo que não devemos tentar tornar as coisas mais simples ou reduzir o clichê, mas que as pessoas não devem começar a usar o Redux e reclamar do clichê envolvido sem entender as trocas feitas e ver o quadro geral.

Quando o Redux foi criado, muitas pessoas (inclusive eu) estavam tentando construir aquilo, e @gaearon obteve a melhor implementação e fez um trabalho muito bom em ferramentas / demo. Ele (e também o Flux) ganhou muita força inicialmente, não apenas por causa da viagem no tempo, mas também porque o conceito não era novo para muitas pessoas e imediatamente parecia natural.

As pessoas veem o Redux como um novo brinquedo brilhante (que parece não ser tão fácil na prática). No entanto, nada no Redux é realmente novo, exceto o fato de que alguém portou esses conceitos de uma maneira elegante para o frontend. Os padrões do Redux e seu ecossistema já são usados ​​em sistemas distribuídos, aplicativos back-end baseados em eventos, design orientado a domínio, e as pessoas com experiência nisso entenderão Redux com muita facilidade.

Infelizmente, as pessoas querem pular etapas e usar o Redux sem saber nada sobre os padrões mais gerais envolvidos. Pessoalmente, eu recomendo a qualquer um que queira construir algo sério no Redux para ter um conhecimento mínimo em sistemas distribuídos. Pode parecer estranho, mas acho que ter esse tipo de experiência pode lhe dar uma vantagem muito séria agora e nos anos que virão.

O que estamos construindo exatamente quando construímos um aplicativo de front-end?

  • Construímos um membro de um sistema distribuído
  • Esse membro contém apenas um subconjunto dos dados do sistema mais geral
  • Esse membro tem capacidades bastante limitadas (armazenamento, largura de banda, estabilidade de rede ...)

Então, tentamos construir algo muito complexo. Temos restrições que são mais difíceis de lidar do que os desenvolvedores de banco de dados, mas queremos que seja mais simples fora da caixa, sem reutilizar o conhecimento anterior de pessoas que realmente pensaram muito sobre esses problemas durante muitos anos. Você não acha que as pessoas já pensaram em como estruturar o estado dentro de um banco de dados? como consultá-lo?

Não estou dizendo que não devemos ser pragmáticos, enviar aplicativos hoje e cometer erros com nosso conhecimento atual, mas sim entender e reconhecer que o que estamos construindo não é mais simples e requer conhecimento adicional. Redux pode ser um bom caminho para obter esse conhecimento, e você pode usá-lo de maneira pragmática no início, mas não subestime o quanto o desenvolvimento de frontend o deixará desconfortável nos anos que virão.

Infelizmente, as pessoas querem pular etapas e usar o Redux sem saber nada sobre os padrões mais gerais envolvidos.

Para o bem ou para o mal, Redux essencialmente venceu a batalha pelo gerenciamento de estado do React. Com isso, vem a capacidade de moldar o ecossistema. Sempre haverá desenvolvedores que querem apenas algo que funcione, e há muitos aplicativos mais simples onde isso é tudo o que é necessário. As pessoas continuarão a usar outras camadas de abstração ou podem ser apresentadas aos padrões gerais corretos por meio de uma biblioteca simples.

Pessoalmente, eu recomendo a qualquer um que queira construir algo sério no Redux para ter um conhecimento mínimo em sistemas distribuídos. Pode parecer estranho, mas acho que ter esse tipo de experiência pode lhe dar uma vantagem muito séria agora e nos anos que virão.

Este é o ponto crucial da questão. Redux como está funciona muito bem para pessoas que o entendem. Simplificar não é necessariamente uma coisa ruim. A maioria das pessoas não está mais escrevendo código assembly, embora compreendê-lo normalmente o ajude a escrever um código melhor. Não é aí que a maioria das pessoas começa.

Muitos outros comentários bons ao redor. Há toneladas de ideias que podemos e devemos explorar mais.

Vamos ver se podemos começar a ter algumas ideias potencialmente acionáveis. Vou começar apresentando um pequeno conceito básico:

Crie um novo pacote chamado, não sei, redux-starter ou algo assim. Esse pacote pode depender de redux-actions , redux-thunk e redux-logger , e talvez um middleware baseado em promessa. Ele forneceria uma função com a assinatura function createReduxStore({reducers, middleware}) {} (baseado no comentário anterior de @Phoenixmatrix ). Não pode nem se incomodar em aceitar middleware?

A função createReduxStore() cuidaria de manipular applyMiddleware e configurar o recarregamento a quente para o redutor de raiz, bem como configurar a extensão Redux DevTools. Se nenhum middleware for fornecido, ele configurará os incluídos por padrão. Isso pode ser parecido com o código de configuração do serviço de loja em ember-redux ou a função configureStore em meu aplicativo de amostra "Projeto Mini-Mek" .

Isso pelo menos minimizaria a quantidade de configuração necessária para começar e forneceria um conjunto modesto de funcionalidades úteis.

Sim, eu gosto disso (bem, não gosto de redux-actions e middlewares baseados em promessas para usuários mais novos, mas vou deixar você se divertir com a bicicleta neste caso). Não se incomodaria em aceitar middleware, apenas createStarterStore (redutor).

Talvez até substitua combineReducer, para que você possa simplesmente fazer:

const store = createStarterStore({
   foo,
   bar,
   baz
});

onde foo bar baz são redutores.

Droga. Acabei de perceber que "uma função de biblioteca que configura HMR para o redutor de raiz" provavelmente não funcionará, porque mesmo que permitíssemos que o usuário passasse o caminho para seu arquivo redutor de raiz, um ou ambos os module.hot.accept() API e require(path) re-import step querem caminhos que são estaticamente analisáveis ​​em tempo de construção e não variáveis. (Eu acho ... que posso estar errado.) Oh, bem.

Mas sim, createStarterStore() poderia aceitar o redutor de raiz ou o objeto de fatias.

Pessoalmente, eu recomendo a qualquer um que queira construir algo sério no Redux para ter um conhecimento mínimo em sistemas distribuídos. Pode parecer estranho, mas acho que ter esse tipo de experiência pode lhe dar uma vantagem muito séria agora e nos anos que virão.

@slorber , concordo com você nessa parte.

Infelizmente, as pessoas querem pular etapas e usar o Redux sem saber nada sobre os padrões mais gerais envolvidos.

Mas não realmente neste. Algumas pessoas sabem sobre os padrões envolvidos no Redux, e é exatamente por isso que escolheram usá-lo. Querer usar algo simples (ou pelo menos mais simples) não significa necessariamente que o usuário não seja capaz de usar uma implementação mais difícil. Isso apenas economiza tempo e esforço.

No local onde trabalho, usamos Redux há um ano e nos descobrimos copiando / colando o mesmo código (apenas modificando um pouco) para adicionar novos recursos à loja, razão pela qual em algum momento sentimos a necessidade de implementar uma camada em cima do Redux, para abstrair esse clichê redundante.
Na minha opinião esta ideia não está apenas simplificando o uso do Redux, mas também reduzindo o clichê para as partes mais comuns (da mesma forma react-redux reduz o clichê ao usar Redux junto com React).

Discussão muito interessante. Meus dois centavos como um usuário redux desde os primeiros dias:

No início, pelo que me lembro, redux era visto mais como um protocolo ou conjunto de convenções razoáveis ​​do que uma estrutura para construir aplicativos. Essa austeridade é parte do motivo pelo qual redux pode ser opressor para novas pessoas e tedioso para escalar sem rolar suas próprias abstrações. Mas a maneira simples como ele cortou a bagunça do estado de gerenciamento em 2015 também é um motivo pelo qual ele decolou, e o minimalismo permitiu que frameworks incríveis como o Apollo pegassem carona no trabalho feito para diferentes projetos (especialmente ferramentas de desenvolvimento) e fornecessem uma forma familiar "cair para um nível inferior" na gestão do estado quando necessário.

Acho que está claro que, como uma biblioteca de "baixo nível", o redux tem sido um grande sucesso e, como uma estrutura rica em recursos para a construção de aplicativos, ainda não chegou lá. Uma coisa para se ter cuidado é que conforme o redux evolui, ele não quebra seu papel como um "protocolo" padrão da indústria para projetos como o Apollo.

Para este fim, talvez o redux atual possa se tornar um pacote como redux-core , e o próprio redux aumenta o nível de abstração para fornecer uma forma recomendada de construção de aplicativos. Claro, pode haver qualquer número de alternativas de nível superior para este redux (como Apollo, ou algo usando sagas?) Usando redux-core ...

Reafirmando as coisas para esclarecimento e ênfase:

Qualquer trabalho fora deste tópico não incluirá grandes mudanças na biblioteca Redux existente :) Uma reformulação do docs é totalmente possível, e pode haver alguns pequenos ajustes, mas o pacote redux permaneceria como está.

Qualquer coisa como o pacote redux-starter que acabei de descrever, ou a abordagem de "estrutura" -y que Dan delineou, seria um novo pacote que depende de redux .

Eu voto que criamos o pacote como sugeriu @markerikson . Assim que tivermos uma base de código, podemos começar a rebater a API, trechos de código e ideias mais aprofundadas. Teríamos então um lugar para criar questões para recursos específicos.

Você pode usar o Delux como um iniciador (jk)

Como um grande usuário do Jumpstate de @tannerlinsley (e agora um dos mantenedores), estou extremamente animado com isso. Minhas razões para usar o Jumpstate são resumidas de forma muito sucinta na postagem original de

Maneira prolixa de dizer: Parece incrível, estou dentro, não tenho certeza de quanto posso contribuir (vou tentar), mas você certamente tem uma líder de torcida.

Eu usei o Jumpstate para ensinar Redux várias vezes e posso dizer com segurança que ele encurtou consideravelmente a curva de aprendizado. Eu penso em Redux como HTTP e Jumpstate como fetch. Eu amo o Redux e escrevi algumas coisas (ridiculamente) complicadas com ele, mas também sei que 90% do caso é mais do que suficiente para ensinar muitas coisas.

Quando você pensa sobre isso, este é um ótimo lugar para estar. Uma das principais reclamações sobre o desenvolvimento de front-end e javascript em geral é "a falta de bibliotecas padrão". Acontece que isso é uma coisa muito nova (TM) , ser capaz de desenvolver aplicativos completos no navegador. A pressão está finalmente aumentando para a necessidade de bibliotecas padrão. É onde estamos agora.

Re: Curva de aprendizagem, teimosia e abstração:

Ajax parece ser uma área onde novos alunos ficam presos, estejam eles aprendendo a usar thunks, sagas ou épicos. Uma área onde eles não parecem ter muita dificuldade é a criação de ações - já que eles são apenas objetos JavaScript antigos, e nós temos a clareza adicional fornecida pela especificação de Ações padrão do Flux. Essa linha de pensamento me levou à pergunta - Por que não desenvolver um Flux Standard Ajax Action ?

Por exemplo

function fetchPosts(page) {
  return {
    type: 'FETCH_POSTS_REQUEST',
    // Ajax request setup
    ajax: {
      url: `/api/posts`,
      method: 'GET',
      data: { page },

      // Optional ajax meta attributes
      meta: {
        // Amount of time to debounce the execution of the request
        debounce: 400,
        // Amount of times to retry the request on failure
        retry: 2,
        // Amount of time before timing out
        timeout: 10000,  
        // The action type that cancels the request
        cancelType: 'CANCEL_FETCH_POSTS',
        // Strategy when multiple FETCH_POSTS_REQUESTs are in flight
        resolve: 'LATEST'
      }
    }
  };  
}

A ação ajax seria tratada pelo middleware (que reagiria à tecla ajax na ação).

Tenho tentado pensar nos motivos pelos quais essa abordagem seria uma má ideia, mas ainda não pensei em nenhum problema.
Alguns benefícios em minha opinião:

  • uma redução dramática na quantidade de ações assíncronas exigidas em seu aplicativo médio (já que as ações assíncronas relacionadas a ajax cairiam)
  • fácil de entender, pois estamos lidando apenas com objetos javascript simples e antigos
  • é declarativo, os detalhes de implementação não são importantes
  • diferentes implementações podem ser trocadas dentro / fora sem quebras
  • é redux idiomático (log de ação ainda faz sentido, serializável etc)

Posso ouvir algumas pessoas invocando o argumento de separação de interesses, mas eu diria que é uma extensão natural do que nossas ações de solicitação de ajax já estão fazendo. Atualmente, eles estão configurando uma ação com um contexto bastante claro, 'FETCH_POSTS_REQUEST' , mas com muito pouco contexto para abstrair a implementação da solicitação ajax. Deixando pouca escolha a não ser executar manualmente a solicitação ajax em outro lugar.

Outra coisa que vem à mente é o encadeamento de ações assíncronas que vi em alguns documentos. Não tivemos a necessidade de encadear solicitações dessa forma, então não tenho certeza de quão amplamente usado esse encadeamento é, mas meu instinto é que estaria fora do escopo do que estou propondo aqui (e talvez não não se enquadram no caso de uso de 90% mencionado nesta discussão).

Concluindo - parece bem possível que uma abstração como essa ajudasse a facilitar a curva de aprendizado e a quantidade de código necessária para escrever aplicativos Redux comuns. Alguém tem alguma opinião sobre essa abordagem - algum fator que atrapalhe o negócio? @markerikson @gaearon

Técnica anterior: redux-axios-middleware

Muitas coisas acontecendo neste tópico.

Em relação à discussão sobre a complexidade do Redux. Pessoalmente, discordo das pessoas que reclama sobre o Redux ser complicado e prolixo. É uma troca que você faz quando usa uma biblioteca de baixo nível baseada nas arquiteturas Flux & Elm. Está declarado na página inicial do Redux que você pode não precisar dele. Mas ainda temos pessoas reclamando de ser complicado.

Redux é encontrar como é. Sorte que a equipe principal está ciente de que ele possui recursos completos e não está disposta a alterá-lo. As abstrações construídas sobre ele são impressionantes e cada uma delas tem seu próprio caso de uso. Isso é o que você esperaria de uma biblioteca de baixo nível boa e bem projetada.

Vejo o problema não no Redux em si, mas na falta de uma maneira progressiva e funcional de aprendê-lo. Como alguns mencionaram, o próprio React tinha o mesmo problema e create-react-app era a solução.

Talvez esse nem seja o problema, já que existem recursos incríveis para isso (por exemplo, a série egghead de Dan). Talvez as pessoas que desejam usar uma biblioteca que resolva problemas complexos sem nenhuma curva de aprendizado sejam o problema.

De qualquer forma, não é disso que trata este tópico.

@markerikson Pessoalmente , estou pronto para ajudar no desenvolvimento deste redux-starter .

_Eu adoraria um nome mais legal_: stick_out_tongue:

O clichê necessário para produzir muitas ações é praticamente a única desvantagem que vejo no redux.

É um nível muito baixo, mas acho ótimo. Esse é um dos motivos pelos quais prefiro o paradigma do estilo Redux ao invés do MobX, por exemplo, embora eu entenda sua utilidade e usaria o MobX. Mas eu só ficaria feliz fazendo isso agora que entendo Redux. Devido ao Redux (ou o padrão Redux em geral), os dados não vão particularmente para os "bastidores". Geralmente, onde quer que o código esteja sendo processado, você o escreveu, e se não, você pode entendê-lo (se você dedicou tempo para aprender, mais sobre isso mais tarde).

O fato é que, quando eu estava aprendendo sobre o Redux, era muito para entender, mas também era simples. Algo pode ser difícil e simples. Porém, por causa disso, pensei: "Uau, esse conceito é tão lógico! Faz tanto sentido que aposto que eu poderia fazer isso sozinho!" Então, para meu primeiro projeto, em vez de usar o pacote Redux, fiz minha própria pequena loja Redux.

Fazer isso não só me ajudou a entender o conceito de Redux, mas aumentou muito meu entendimento do próprio Javascript! (Isso é da perspectiva de alguém que não sabia quase nada sobre os conceitos de programação funcional antes disso, então sua milhagem pode variar.) O conceito de Redux é realmente brilhante em sua simplicidade, mas também incrivelmente poderoso.

Eu acho que o fato é que como o Redux é tão popular, é, uhh, "buzzwordy-ness" pode distrair os recém-chegados de quão bom ele funciona em Javascript. Portanto, a mentalidade deles pode ser "ok, tenho React, Redux, etc etc, agora vou ser um programador incrível e fazer um ótimo aplicativo!" Não que haja algo de errado com isso. Mas eles podem se concentrar apenas no desejo de usar uma ferramenta novinha em folha para agilizar o processo de desenvolvimento, sem entender o que faz a ferramenta funcionar.

Uma vez que o conceito é entendido, torna-se muito fácil fazer com que o Redux (ou qualquer padrão parecido com o Redux) faça todo tipo de coisa. Eu gosto disso pelo mesmo motivo que gosto do React em vez de outras ferramentas (ainda excelentes) como o Angular. _É apenas Javascript._ É assim que o Javascript funciona!
Se o clichê necessário puder ser reduzido por meio de algum paradigma, isso seria ótimo, mas acho que é um pequeno preço a pagar por powaaaaaa ilimitado.

IMO tudo isso "a verbosidade é uma troca" é apenas masoquismo; a verbosidade não está a serviço de nada, é um sacrifício que você faz para usar o Redux. Não estou culpando o Redux ou o javascript, só quero ressaltar que essa não é uma complexidade essencial. Elm gerencia tudo que Redux consegue em menos linhas e código mais simples.

Então, escrevemos mecanicamente o clichê. Jumpstate e similares tornam a vida mais fácil, mas há limites para o que você pode fazer em tempo de execução, e com jumpstate de texto / fluxo não ajuda muito. Mas codegen é difícil e ninguém quer adicionar mais nada ao seu já sobrecarregado sistema de compilação.

Se eu pudesse ter algo como o código do Elm que foi traduzido para o Redux idiomático ... Fique tranquilo.

Aqui estão algumas das minhas ideias, espero não repetir os comentários anteriores:

Os criadores de ação podem ser usados ​​como tipos de ação

actions.js

export function increase() {}

reducer.js

import { increase } from './actions.js';
export default handleActions({
    [increase]: (state) => state + 1
}, 0);

Como as funções têm referências exclusivas, podemos tratá-las como identificadores de ações. Não é compatível com FSA, mas economiza muito código e evita erros.

As ações podem ser despachadas de forma assíncrona

async function a() {

}
async function b() {
}
store.dispatch(a());
store.dispatch(b()); // b() will be dispatched after a() resolves

Dessa forma, os criadores de ações podem ser funções assíncronas e, ainda assim, despachar um após o outro. Como vejo em muitas situações, as pessoas não precisarão usar soluções baseadas em middleware e isso economizará muito código clichê.
Este conceito é implementado por uma fábrica de promessa em Delux

redux === padrão

https://github.com/Emilios1995/redux-create-module

mas acho que essa função pode salvar completamente sua vida.

Vale a pena diferenciar entre dois conjuntos diferentes de ideias acontecendo neste tópico:

  • uma estrutura baseada em redux de "serviço completo"
  • recursos adicionais no redux core

Eu concordo com @markerikson que redux core não deve se tornar um framework em si, e eu entendo porque alguém iria querer manter redux-thunk e react-redux em pacotes separados. No entanto, acredito que haja espaço e precedentes para novas "funções auxiliares" no redux core.

Redux tem uma área de superfície API razoavelmente pequena: createStore , applyMiddleware , combineReducers , bindActionCreators e compose . Mas a maioria delas são funções de conveniência. Apenas createStore é estritamente necessário para o Redux funcionar. Por que qualquer um deles pertence ao núcleo?

  • applyMiddleware cria uma interface simplificada para armazenar realçadores. Mas o mais importante, applyMiddleware suporta o middleware _interface_ como uma forma padrão de adicionar efeitos aos armazenamentos redux. O ecossistema de middleware é possível porque applyMiddleware tem uma interface comparativamente simples e permite que os usuários executem muitos middleware de uma vez.

  • combineReducers fornece uma forma conveniente de composição do redutor. Está longe de ser a única maneira de compor redutores, mas certamente é um dos padrões mais úteis. Mas sua presença no redux core significa que não é apenas comum, mas _ubíquo_. Cada aplicativo Redux não trivial que encontrei usa combineReducers para criar o redutor de raiz. O outro lado disso é que, como combineReducers é a única forma de composição redutora que vem com o Redux, muitos usuários parecem acreditar que é a única forma de composição redutora que existe.

  • bindActionCreators reduz alguns dos clichês em torno de ações de despacho. Mas, perversamente, bindActionCreators também é indiretamente responsável por parte da reputação do Redux de clichê. Isso ocorre porque a mera existência de bindActionCreators incentiva o uso de criadores de ação. Isso é particularmente visível quando se compara a prevalência de criadores de ação (que são "endossados" por bindActionCreators ) e seletores (que são documentados, mas não têm função central equivalente). Já vi muitas bases de código usando react-redux onde mapStateToProps são sempre seletores "sob medida", mas mapDispatchToProps é sempre um mapa de objetos de criadores de ações pré-escritos.

Nenhum deles é essencial para a funcionalidade do Redux, mas todos são essenciais para sua usabilidade. Nenhuma dessas funções limita a flexibilidade inerente do Redux, mas ao reificar padrões comuns em funções que podem ser chamadas, elas tornam as escolhas menos assustadoras. E cada uma dessas funções auxiliares levanta outras questões:

  • Se o middleware é uma simplificação de intensificadores de loja, existem outras simplificações que poderiam ser amplamente úteis?
  • Que outras formas de composição de redutor poderiam ser implementadas em vez de meramente documentadas? Objetos redutores ? Redutores dependentes ? Composição linear ?
  • A integração da nova seleção levaria as pessoas a criar e compor seletores onde antes? Isso seria um resultado positivo?

Mesmo que as respostas a todas essas perguntas sejam negativas, acho que prestamos um péssimo serviço a nós mesmos e à comunidade ao nos recusarmos a sequer considerar suas premissas.

@modernserf : Primeiramente, obrigado por seus comentários, assim como por seus outros pensamentos recentes sobre o Redux. Eles são todos _extremamente_ valiosos e informativos, e provavelmente devem ser leitura obrigatória para qualquer pessoa neste tópico. Então, vou vinculá-los aqui:

É muito interessante que você traga isso à tona, por causa da história envolvida (que eu acabei de passar muito tempo pesquisando para meu post O Tao de Redux, Parte 1 - Implementação e Intenção . Em particular, redux-thunk foi originalmente construído diretamente no Redux , e react-redux só foi separado mais tarde também .

Você está certo ao dizer que esses utilitários de fato codificam certos padrões de uso. Dito isso, esses utilitários são incluídos porque codificam os padrões de uso _intendidos_: composição de redutores de fatia, um pipeline de middleware para comportamento assíncrono e outro comportamento centralizado e criadores de ação vinculada para simplificar o processo de despacho de ações de componentes (particularmente, passar funções ao redor para componentes filhos). De forma semelhante, embora Reselect não esteja no núcleo, Dan encorajou explicitamente sua criação .

Então, sim, qualquer um "poderia" tê-los escrito, mas, ao integrá-los, incentivamos as pessoas a usar essas ferramentas específicas de maneiras específicas. Definitivamente concordo com isso.

De acordo com suas últimas três perguntas:

  • _Acho que você poderia dizer que middleware é "uma simplificação dos potenciadores de loja", embora eu não ache que isso lhes faça justiça. Em vez disso, é um intensificador de armazenamento para um propósito muito especializado. No que diz respeito a outros trabalhos relacionados a realçadores de loja: Dan disse que a maior parte do núcleo do Redux que ele ainda gostaria de modificar está relacionada a como os realçadores são inicializados. Na verdade, há dois PRs "concorrentes" para alterar a implementação do intensificador de loja que estão abertos há muito tempo: a versão de @acdlite em # 1706 e a versão de @jimbolla em # 2214. Também é interessante observar que Jim reuniu uma lista de todos os aprimoradores de loja conhecidos para ajudar a analisar como a comunidade os está realmente usando. Eu sei que a proposta de Jim pretendia ajudar os autores de realçadores a simplificar os comportamentos comumente vistos. Então, essa é uma direção que poderia ser mais explorada.
  • Definitivamente, há muitos outros padrões de composição e estrutura de redutor por aí. Não sei exatamente o que poderíamos fazer no que diz respeito aos redutores "dependentes", uma vez que isso é muito mais um caso de uso de nicho e parece ser bastante específico para o aplicativo. Por um longo tempo, Dan fechou quaisquer PRs que propusessem adicionar algum tipo de terceiro argumento a combineReducers (e houve _muito_ deles), mas finalmente permitiu que # 1768 fosse adiante para um enquanto. Esse PR também parou.
  • O caso de uso mais comum para seletores parece ser a extração direta de bits de estado e passando-os como adereços nomeados. Também temos um PR aberto para React-Redux para adicionar uma sintaxe abreviada de objeto para mapState , e recebemos inúmeras solicitações para isso, embora você possa fazer a mesma coisa com createStructuredSelector Reselect.

Como documentei naquele post "Tao of Redux", os objetivos declarados eram manter a API central do Redux o mais mínima possível e encorajar um ecossistema em cima dela . Além disso, no início do desenvolvimento do Redux, Andrew fez um comentário sobre a intenção de "abençoar" certos plug -

Como gaearon disse uma vez, (não me lembro onde ... provavelmente Slack) pretendemos ser como as bibliotecas Koa of Flux. Eventualmente, quando a comunidade estiver mais madura, o plano é manter uma coleção de plug-ins e extensões "abençoados", possivelmente sob uma organização GitHub reduxjs.

Anteriormente, eu havia proposto algum tipo de biblioteca de abstração de "configuração fácil do Redux" ou algo parecido. Algo assim, ou pelo menos aquela lista de complementos "abençoados", seria suficiente para o que você está pensando? (E, na verdade, você também fez no primeiro comentário deste tópico.) Se não, alguma proposta ou ideia adicional?

Eventualmente, quando a comunidade estiver mais madura, o plano é manter uma coleção de plug-ins e extensões "abençoados", possivelmente sob uma organização GitHub reduxjs.

Isso é o que eu também faria, embora provavelmente daria um passo adiante: eu reestruturaria o projeto em um monorepo, onde o pacote redux atual se tornaria algo como @redux/core , abençoado bibliotecas como reselect e redux-action são trazidas para o repositório e o namespace, e o pacote redux si apenas reexporta todos esses pacotes em um único namespace.

Esse _tipo de_ satisfaz a restrição de não modificar o núcleo redux. Além disso, a versão estendida seria um superconjunto estrito do - e, portanto, compatível com as versões anteriores - o núcleo. Os novos recursos seriam puramente opt-in e não teriam acesso especial ao estado privado. No que diz respeito ao "inchaço" - cada uma dessas bibliotecas é pequena para começar, e elas são escritas de uma forma que seria trivial sacudi-las.

Também temos um PR aberto para React-Redux para adicionar uma sintaxe abreviada de objeto para mapState, e recebemos inúmeras solicitações para isso, embora você possa fazer a mesma coisa com createStructuredSelector de Reselect.

Eu acho que isso deveria te dizer algo.

A estrutura monorepo que estou sugerindo é basicamente a estrutura usada por Lodash. Agora - Lodash é uma biblioteca interessante para modelar: é uma coleção enorme de funções, muitas das quais são triviais para implementar você mesmo. Quase todas as funções em Lodash poderiam ser mais flexíveis como uma "receita" - groupBy é realmente um _pattern_ afinal; quem somos nós para dizer em quais estruturas de dados você o usa?

E cada função Lodash também está disponível em sua própria biblioteca _a la carte_. Não há benefício _funcional_ em import { groupBy } from "lodash" relação a import groupBy from "group-by" . Por que devo lidar com o abalo de árvores quando posso simplesmente instalar o que preciso?

Mas a experiência de usar Lodash é fundamentalmente diferente do que usar receitas ou nanolibliotecas. Você sabe que se estiver fazendo algo com um array e tiver a sensação de que está se repetindo, provavelmente há uma função Lodash para fazer isso. Você não precisa procurar uma receita, não precisa instalar nada - é provável que você nem mesmo precise adicionar outra linha de importação ao arquivo. Está removendo apenas a menor quantidade de atrito, mas nossos dias são cheios de momentos como este e isso aumenta.

Espero que você não se importe se eu adicionar meus próprios 2 centavos, de uma perspectiva diferente.

As escolas de pensamento CQRS , Event Sourcing e, em última análise, Domain Driven Design são os maiores ancestrais que nos deram Flux e Redux . Embora essas influências sejam ocasionalmente citadas , Redux e suas ferramentas descendentes pegaram a maior parte de sua terminologia de API de implementações de Fluxo e Fluxo que eram populares na época. Tudo bem, mas acho que estamos perdendo alguma oportunidade de lucrar com a exposição que os desenvolvedores podem ter para essas ideias.

Para dar dois exemplos da diferença: Na maioria das discussões sobre Event Sourcing que vi, Redux Actions seria referido como Events . Redux ActionCreators seriam referidos como Comandos . Eu acho que há alguma clareza e semântica adicionais que vêm de graça com essa terminologia também. Os eventos são dados registráveis ​​e serializáveis. Os eventos descrevem o que aconteceu no tempo passado. Os eventos podem ser reproduzidos. Os eventos não podem ser cancelados. Os comandos têm um caráter imperativo. Comandos acionam eventos .

Eu suspeito que o Event Sourcing como um padrão arquitetônico ganhará popularidade na próxima década, e eu acho que o Redux poderia ganhar algumas vantagens de usabilidade, clareza e facilidade de uso alinhando a API e a discussão mais de perto com a comunidade mais ampla.

Acho que essa discussão já foi espancada até a morte: https://github.com/reactjs/redux/issues/351

Oh, eu não sabia disso, obrigado! : +1:

Parece que o # 351 foi fechado porque, no momento, nenhuma ação poderia ser realizada. Se estamos em um momento em que estamos reconsiderando as decisões da API e a linguagem que usamos, este parece ser o momento apropriado para ressurgir a ideia, para mim.

Posso ser mais concreto.

Esta é minha ideia de como pode ser uma API inspirada em expressões idiomáticas de Event Sourcing :

Conceitos

  • Fluxo de eventos observáveis
  • O Event Stream tem um conjunto bem tipado de eventos suportados
  • Envio de comandos para o fluxo de eventos
  • Um ou mais clientes consomem o fluxo de eventos

API

import { createEventStream, createProjection } from 'redux';

// Initialize the event stream separately from the store.  This becomes the one
// true source of truth for your application.
const eventStream = createEventStream({
  // Commands are the only thing that we want to couple to the eventStream.  The 
  // set of events which may end up in an eventStream should be easy to predict.
  //
  // A definition like this supports static analysis inference well for 
  // consumers that can leverage it.
  increment: () => ({ type: 'INCREMENT' }),
  decrement: () => ({ type: 'DECREMENT' }),
});

// Multiple stores with disjoint or overlapping data can be used to consume the 
// same event stream.
const store = createProjection(eventStream, reducer, init);
const adminStore = createProjection(eventStream, adminReducer, init);

// We don't need a jargon term ("Middleware"), or a dedicated hook to handle 
// async anymore.  We just register more subscribers to the eventStream.
eventStream.subscribe(myCustomMiddleWare);
eventStream.subscribe(sendEventsToAnalytics);
eventStream.subscribe(logEventsForPlayback);

// Calls to commands can be wrapped with React Providers or container components 
// in the same way that Redux currently does.  They can also be called directly.
eventStream.increment();

@ajhyndman : embora eu aprecie a sugestão e a discussão, aquela bicicleta foi totalmente pintada e o cavalo fugiu do celeiro (para misturar completamente as metáforas). Dan optou por usar a terminologia do Flux em vez dos termos CQRS / ES, e não há planos para alterar as APIs principais ou os termos usados ​​para os conceitos do Redux.

(Além disso, embora eu tenha zero estatísticas para comprovar isso, acho que neste ponto há mais pessoas familiarizadas com o uso de "ações" e "criadores de ações" do Redux do que com a terminologia CQRS / ES, pelo menos dentro da comunidade JS. )

Com certeza tenho a impressão de que essa conversa já existiu antes, e há um forte desejo de não abri-la novamente. 😄 Não vou pressionar muito mais aqui. (Eu estaria interessado em ler ou continuar esta conversa em outro lugar, se houver um ponto de contato melhor.)

Claro, você também está certo de que há um fator de entrincheiramento, e mudar toda a superfície e terminologia da API seria caro neste momento.

Eu ainda argumentaria que há oportunidade para as comunidades Event Sourcing e Redux aprenderem umas com as outras.

  • Quais abstrações possíveis poderiam ser criadas para simplificar o processo de aprendizado e uso, mas sem realmente ocultar o Redux (e, com sorte, forneceria um caminho de migração / aprendizado para o Redux "básico")?

Mesmo sem emprestar a terminologia ou alterar a API, acho que podemos encontrar vantagens. Por exemplo, tive sucesso ao apresentar Redux às pessoas, descrevendo uma loja como "um contêiner de estado em que currentState é uma" função pura de "(é derivado de, ou reduzido de) uma lista apenas de anexos (ou um fluxo) de Ações ".

Olhando mais para o futuro, acho que é inteiramente possível implementar e abstrair uma infraestrutura de servidor semelhante ao redux (consulte: Apache Samza e alguns dos outros trabalhos da equipe de engenharia do LinkedIn). Se aspirarmos a isso, então também deve ser possível usar abstrações semelhantes para gerenciamento de estado de cliente e servidor! Se podemos conseguir isso, por que não uma loja Redux isomórfica e persistente?

Quaisquer conceitos que as comunidades JavaScript e de infraestrutura sejam capazes de reunir, ou mapear facilmente entre eles, mais rapidamente espero que essas oportunidades se tornem aparentes e mais expressivas serão as abstrações.

Acho que estou ficando um pouco animado com algumas dessas ideias! Espero que você me perdoe pela palavra despejo.

Nota lateral: parece ser possível criar uma API wrapper semelhante a fluxo de eventos para Redux que implementa a superfície que sugeri acima!

https://github.com/ajhyndman/redux-event-stream

@ajhyndman Acho que o wrapper é a maneira certa de acompanhar a sua ideia aí 👍

Relacionado ao trabalho de engenharia do Samza e do LinkedIn que você mencionou, se outros não leram / assistiram à palestra maravilhosa Virando o banco de dados do avesso com o Apache Samza , encontre uma hora para fazê-lo algum dia! Acho que vi Dan mencioná-lo em um readme ou tweet em algum momento. Essa conversa mudou a forma como ver bancos de dados e gerenciamento de estado para sempre e é um primo idealógico muito próximo do redux.

Esse vídeo é incrível! Na verdade, é também o segundo item na lista de agradecimentos no README do redux repo.

Ei pessoal!

Sem estar ciente da existência desta discussão, tenho desenvolvido uma biblioteca que é de uma maneira uma resposta direta à @markerikson 's perguntas originais e pancadas off a maioria das coisas de @gaearon' s lista .

A biblioteca é chamada Kea :

screen shot 2017-08-06 at 13 10 03

É uma abstração sobre redux, redux-saga e reselect. Exceto pela cola que os conecta, Kea não pretende criar nada novo e expõe criadores e redutores de ação redux bruta, sagas de saga redux bruta e seletores de nova seleção brutos conforme necessário. Não inventa um novo conceito.

O Kea oferece suporte a muitos modos diferentes de operação: você pode usá-lo autônomo, conectado aos componentes React, alinhados acima aos componentes React ou até mesmo conectado dinamicamente aos componentes React, onde a entrada para os seletores depende dos props do componente React.

Eu pessoalmente o uso com dois grandes aplicativos: um mercado para aulas particulares e um enorme software de rastreamento de frotas. Além disso, conheço pessoas que criaram seus próprios aplicativos com ele. Por ser tão útil para nós, gastei um tempo considerável limpando-o e escrevendo a documentação .

Para mim, essa biblioteca sempre reduziu muito o clichê, embora permaneça fiel ao núcleo do redux em si.

Enfim, chega de conversa, aqui está um código. Este é um exemplo do que chamo de "kea embutido" - em que a lógica é anexada diretamente ao seu componente. Este modo é ótimo para quando você está apenas começando ou como uma alternativa ao setState do React.

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { kea } from 'kea'

@kea({
  actions: () => ({
    increment: (amount) => ({ amount }),
    decrement: (amount) => ({ amount })
  }),

  reducers: ({ actions }) => ({
    counter: [0, PropTypes.number, {
      [actions.increment]: (state, payload) => state + payload.amount,
      [actions.decrement]: (state, payload) => state - payload.amount
    }]
  }),

  selectors: ({ selectors }) => ({
    doubleCounter: [
      () => [selectors.counter],
      (counter) => counter * 2,
      PropTypes.number
    ]
  })
})
export default class Counter extends Component {
  render () {
    const { counter, doubleCounter } = this.props
    const { increment, decrement } = this.actions

    return (
      <div className='kea-counter'>
        Count: {counter}<br />
        Doublecount: {doubleCounter}<br />
        <button onClick={() => increment(1)}>Increment</button>
        <button onClick={() => decrement(1)}>Decrement</button>
      </div>
    )
  }
}

No caso de seu aplicativo crescer e mais lugares precisarem de acesso às ações increment e decrement ou counter prop, você pode simplesmente dividir seu código assim:

// counter-logic.js
import PropTypes from 'prop-types'
import { kea } from 'kea'

export default kea({
  actions: () => ({
    increment: (amount) => ({ amount }),
    decrement: (amount) => ({ amount })
  }),

  reducers: ({ actions }) => ({
    counter: [0, PropTypes.number, {
      [actions.increment]: (state, payload) => state + payload.amount,
      [actions.decrement]: (state, payload) => state - payload.amount
    }]
  }),

  selectors: ({ selectors }) => ({
    doubleCounter: [
      () => [selectors.counter],
      (counter) => counter * 2,
      PropTypes.number
    ]
  })
})
// index.js
import React, { Component } from 'react'
import { connect } from 'kea'

import counterLogic from './counter-logic'

@connect({
  actions: [
    counterLogic, [
      'increment',
      'decrement'
    ]
  ],
  props: [
    counterLogic, [
      'counter',
      'doubleCounter'
    ]
  ]
})
export default class Counter extends Component {
  render () {
    const { counter, doubleCounter } = this.props
    const { increment, decrement } = this.actions

    return (
      <div className='kea-counter'>
        Count: {counter}<br />
        Doublecount: {doubleCounter}<br />
        <button onClick={() => increment(1)}>Increment</button>
        <button onClick={() => decrement(1)}>Decrement</button>
      </div>
    )
  }
}

Experimente e leia os documentos para saber mais sobre os efeitos colaterais do redux-saga e outros recursos que você pode usar.

O feedback para Kea tem sido extremamente positivo até agora, citando uma edição : "Mais pessoas deveriam usar KeaJS para tornar o mundo redux um lugar melhor! 👍" :)

Obrigado pelo seu tempo e por ler até aqui! :)

Parece legal! não estou gostando muito das cordas mágicas, embora 'increment'

Essa discussão avançou em outro lugar? O Kea é o resultado mais correto geralmente aceito?

@lucfranken : não, a discussão acabou.

Se você está procurando uma abstração de nível superior em relação ao Redux, então Kea é provavelmente uma boa opção. Se você está procurando um "pacote inicial Redux" que simplifica o processo de configuração da loja, talvez seja necessário dar uma olhada em alguns. Eu sei que já vi algumas coisas assim na selva, mas não temos nenhuma biblioteca oficial como essa agora.

Jogando meu chapéu no ringue aqui. É assim que resolvo esse problema: https://github.com/HenrikJoreteg/redux-bundler

Eu pessoalmente acho que é uma grande simplificação e redução do clichê.

É como venho construindo tudo o que construí recentemente.

Ei, na minha empresa acabamos de abrir o código de uma biblioteca que gerencia a camada de rede e remove muitos clichês do Redux. Ele provou ser um sucesso para nós, mas experimente você mesmo: https://github.com/Brigad/redux-rest-easy/ (artigo médio: https://engineering.brigad.co/introducing-redux-rest-easy -6e9a91af4f59)

1_327nnvo3cuaqc-dsqpoq7w

aqui está minha abordagem para reduzir redux boilerplate
image

https://github.com/zhDmitry/restate

Como um necroing altamente tardio do tópico, um tempo atrás eu pedi um feedback no Twitter sobre o que "clichê" significa para as pessoas:

https://twitter.com/acemarke/status/969040835508604929

Retorno do Necro-Thread!

Por minha edição do primeiro comentário neste tópico, as idéias discutidas aqui foram transformadas em nosso pacote Redux-Starter-Kit . Por favor, experimente e veja o quanto ele pode ajudar a simplificar seu uso do Redux!

Esta página foi útil?
0 / 5 - 0 avaliações