Ember.js: [Glimmer 2] "Backtracking re-render" agora é uma afirmação

Criado em 29 jul. 2016  ·  63Comentários  ·  Fonte: emberjs/ember.js

Retroceder a renderização se refere a um cenário onde, no meio do processo de renderização, você modificou algo que já foi renderizado.

Por exemplo:

{{foo}} {{foo-bar parent=this}}
// app/components/foo-bar.js

export default Ember.Component.extend({
  init() {
    this._super(...arguments);
    this.get('parent').set('foo', 'bar');
  }  
});

Como você pode ver, no momento em que o componente foo-bar é instanciado e renderizado, já usamos o valor foo do contexto pai para preencher o {{foo}} encaracolado. Porém, em seu construtor, ele estava tentando modificar o mesmo valor, portanto. "retrocesso".

Este é um exemplo bastante extremo, mas ilustra o problema. Além de init , didInitAttrs , didReceiveAttrs , willInsertElement e willRender também acontece sincronizadamente durante o processo de renderização. Além disso, o retrocesso costuma ser um problema decorrente do comportamento de propriedades vinculadas bidirecionais.

Este comportamento sempre não foi confiável, mas foi parcialmente compatível com uma suspensão de uso (desde o Ember 1.13):

You modified ApplicationController.foo twice in a single render. This was unreliable in Ember 1.x and will be removed in Ember 3.0

Desde 1.13, Ember apoiou isso fazendo imediatamente uma segunda renderização quando o retrocesso foi detectado (e então repetindo até que o sistema se estabilize). Essa estratégia em si pode ser uma fonte de problemas de desempenho. Em casos extremos, isso pode causar um loop infinito.

No Glimmer 2, embora a re-renderização extra seja relativamente barata, a contabilidade extra para detectar um retrocesso set não é. Uma das vantagens do sistema Glimmer 2 é que ele não precisa configurar observadores para rastrear mudanças. Além disso, certas otimizações no Glimmer 2 permitem que o sistema pule a travessia de subárvores quando ele não sabe que nada dentro delas mudou.

Juntos, esses fatores significam que não podemos detectar prontamente esses retrocessos set s (ou se algo "já foi renderizado" ou não) sem fazer uma grande quantidade de contabilidade extra e intencionalmente derrotar essas otimizações.

Já escrevemos o código para oferecer suporte a isso, mas devido à natureza não confiável do recurso e aos custos (muito significativos) de contabilidade, hesitamos em habilitá-los automaticamente para todos sem saber se ainda é necessário.

Como um compromisso, atualmente apenas executamos a detecção no modo de desenvolvimento e transformamos a mensagem de reprovação em uma declaração do modo de desenvolvimento (erro de hardware). No modo de produção, o código de detecção é eliminado e o retrocesso não funciona.

Mantivemos a facilidade de oferecer suporte a esse recurso (sem a asserção) na base de código por trás de um segundo sinalizador de recurso. O código está sendo testado continuamente no CI, no entanto, está desabilitado por padrão até que tenhamos informações de uso suficientes para determinar as próximas etapas.

Se você acredita que tem padrões de uso que são afetados por isso, forneça o máximo de detalhes possível sobre o seu cenário abaixo. É muito possível que haja alternativas e / ou soluções direcionadas que possamos usar e que não requeiram uma mudança total no motor. Portanto, seria útil se você fornecer informações básicas e contexto sobre seu uso, em vez de apenas nos mostrar pequenos trechos de código de sua base de código.

Ember 2.10 Inactive

Comentários muito úteis

Isso não foi mencionado na postagem do blog 2.10 e me pegou de surpresa, pois o aviso de suspensão de uso dizia que ele seria compatível até o 3.0, conforme mencionado acima.

Todos 63 comentários

Para sua informação, tivemos alguns desses avisos em nosso aplicativo. Especificamente, atualizamos algumas propriedades de um serviço em init de um componente, o que faria com que algo mais na página fosse renderizado de maneira diferente.

É muito simples corrigir esse aviso agendando a alteração da propriedade no próximo ciclo de execução. Levei cerca de uma hora para rastrear e corrigir todos os avisos em nosso aplicativo (bastante grande). Embora esta seja tecnicamente uma mudança significativa, concordo com sua avaliação, mesmo que tenha me causado algum trabalho extra.

@fivetanley melhorar a mensagem de erro aqui parece bom. Eu sei que @krisselden e @stefanpenner têm um fluxo de trabalho para rastrear esses problemas, talvez eles possam ajudar a lhe dar algumas instruções sobre isso.

@joukevandermaas run.next () não é uma boa solução para esse erro, embora eu entenda se você está sobrecarregado com esses erros, porque você iria lá. É melhor tentar entender por que o fluxo de retorno de dados está invalidando coisas que já foram renderizadas.

Provavelmente, se você definir props em um serviço que pode ser injetado em qualquer componente, isso aumenta as chances de que esse conjunto invalide algo que já foi processado. Em geral, o padrão deve ser que set () seja usado apenas no estado interno durante os ganchos de renderização, não vinculado a entrada ou serviços e ou set () seja usado em um evento, o estado de entrada deve ser definido pelo tempo que o material é renderizado.

@joukevandermaas run.next () não é uma boa solução para esse erro,

fazer isso causa problemas de desempenho, já que o glimmer2, neste caso, está informando "trabalho duplicado está acontecendo, você realmente não quer isso se quiser um aplicativo com desempenho". Onde antes, a brasa absorveria isso, mas resultaria em uma grande penalidade de desempenho.

Temos mais algumas tarefas de compartilhamento de conhecimento a fazer aqui ... Em última análise, acreditamos que este é um caminho saudável para os aplicativos. Mas precisamos ter certeza de que todos tenham as ferramentas + conhecimento disponíveis para se beneficiar :)

Como uma pessoa que segue o Ember relativamente de perto (twitter, aqui no github, listas de e-mail, etc), este problema me ocorreu, então eu suspeito que isso pode pegar outras pessoas de surpresa se cair como parte do Ember 2.10, especialmente porque o aviso de descontinuação associado a ele afirma especificamente que o comportamento terá suporte até 3.0. Eu não acredito que já tenha visto isso socializado em qualquer lugar que esse comportamento não funcione no Glimmer 2 (embora eu possa simplesmente não tê-lo visto).

suspeite que isso pode pegar outros de surpresa se cair como parte do Ember 2.10, especialmente porque o aviso de depreciação associado a ele afirma especificamente que o comportamento será compatível até 3.0. Eu não acredito que já tenha visto isso socializado em qualquer lugar que esse comportamento não funcione no Glimmer 2 (embora eu possa simplesmente não tê-lo visto).

sim, precisamos melhorar algumas mensagens / detalhes aqui.

Vejo que isso foi feito na versão 2.10. Isso será mencionado na postagem do blog de lançamento do 2.10?

Isso não foi mencionado na postagem do blog 2.10 e me pegou de surpresa, pois o aviso de suspensão de uso dizia que ele seria compatível até o 3.0, conforme mencionado acima.

Eu tenho um padrão de uso que é afetado por isso. Tenho certeza de que o problema deve ser meu padrão de uso, e não essa mudança em particular, mas adoraria saber como seria um bom padrão de uso alternativo!

Basicamente, tenho uma página que mostra um conjunto filtrável de dados e, para conseguir isso, estou usando um valor calculado de Ember para filtrar os dados com base no valor de vários parâmetros de consulta na página. No entanto, para evitar que entradas inválidas (por exemplo, não letras ou números) sejam adicionadas aos parâmetros de consulta da entrada do usuário, tenho o seguinte padrão:

 filteredModel: Ember.computed('model', /*list of individual query params*/, function(){
    let model = this.get('model').filterBy('pdf.pdf_path.url'); //removes all records that don't have a pdf uploaded
    this.get('queryParams').forEach((filter)=> { // for each possible filter
      if ((this.get(filter).length > 0)) { //if the filter has content...
        //guardian pattern to prevent invalid inputs
        let valid = new RegExp('^[A-Za-z0-9 _]*[A-Za-z0-9][A-Za-z0-9 _]*$');
        while (this.get(filter).length > 0 && !valid.test(this.get(filter))){
          this.set(filter, this.get(filter).slice(0,-1));
        }
        //block of code where the model gets filtered
        //...
        //...
    });
    return model;
  }),

Então, basicamente, quando calculei a aparência do modelo filtrado, se algum dos valores do filtro contiver caracteres inválidos, retirei o último caractere até que se tornem válidos. Alguém tem uma sugestão de uma maneira mais limpa de fazer a verificação de validade dessas entradas?

Isso também nos pegou de surpresa - principalmente porque não vimos nenhuma mensagem de aviso quando o aplicativo estava sendo executado com 2.9. Quando atualizamos para 2.10, o aplicativo não carrega e faz referência a esse erro. Alguém já viu esse comportamento?

@revanar Eu poderia estar totalmente didReceiveAttrs . De acordo com minha experiência, encontrei o erro "retrocesso de renderização", acho que mover a operação set para fora do CP deve fazer com que o erro desapareça.

Estamos passando por um momento difícil com isso também. Corrigi muitos dos problemas, mas uma instância que estamos vendo desse erro de reprovação é intrigante.

Assertion Failed: You modified transitioningIn twice on <app<strong i="6">@component</strong>:link-to::ember1159> in a single render.

Parece que uma falha está acontecendo porque uma propriedade interna do ember está sendo atualizada mais de uma vez. Infelizmente, ele se reproduz durante nossos testes de selênio, por isso é difícil de depurar (o driver selênio evita que as ferramentas de desenvolvimento funcionem durante a execução do teste). Rastreei pelo menos uma instância do problema para uma chamada controller.transitionToRoute feita no final do nosso processo de login, mas parece acontecer em vários cenários diferentes.

Não tenho certeza de como proceder para solucionar isso.

@chancancode mencionou um sinalizador de recurso para desativar esse erro de https://github.com/emberjs/ember.js/blob/master/FEATURES.md. Alguém sabe o que é a bandeira?

Para a nossa migração ember 2.10 também, este é o principal ponto de dor. Também corrigimos muitos desses problemas. Parece que não existe uma estratégia única / clara para corrigir esses erros. Tentamos as seguintes abordagens, dependendo do caso de uso

  1. Envolvendo o código em Ember.run.next
  2. Movendo qualquer código setter de computed properties para ganchos de ciclo de vida ou para event handlers , sempre que possível.
  3. Tentar uma combinação diferente de ganchos de ciclo de vida para componentes

Temos tido muitas dificuldades com isso também. Nos últimos anos, acumulamos uma grande quantidade de menus suspensos que selecionam automaticamente o primeiro elemento de um determinado tipo do cache de armazenamento de dados do ember. Isso causa uma nova renderização, pois algumas partes da página são orientadas pela seleção suspensa. Não tenho certeza do que fazer, pois não quero repetir o mesmo código para preencher e selecionar o primeiro item da lista em cada página em que os menus suspensos são usados.

@scottmessinger Obrigado pelo feedback. Usar um componente acabou funcionando muito bem. Consegui me livrar do erro de retrocesso e acho que meu código está um pouco mais limpo para isso.

Kris Selden tem uma dica útil para depurar estes:

screen shot 2016-12-12 at 13 10 44

Descrevi as etapas com mais detalhes aqui: https://github.com/GavinJoyce/backtracking/pull/1#issuecomment -266427152

Estou trabalhando para melhorar a mensagem de afirmação de retrocesso . Elaborei uma compilação 2.10.2-with-improved-backtracking-assertion que inclui estas mensagens melhores:

Antes:

Você modificou message.message_goal.description duas vezes em <(subclass of Ember.Model):ember3486> em uma única renderização. Isso não era confiável e lento no Ember 1.xe não é mais compatível. Consulte https://github.com/emberjs/ember.js/issues/13948 para obter mais detalhes.

Depois de:

Você modificou message.message_goal.description duas vezes em <(subclass of Ember.Model):ember3486> em uma única renderização. Ele foi renderizado em component:message-edit-expanding-container-component e modificado em component:rules/predicate-date-value-component . Isso não era confiável e lento no Ember 1.xe não é mais compatível. Veja # 13948 para mais detalhes.

Tenho mais algumas coisas a fazer antes de ficar pronto, mas seria muito útil se algumas pessoas experimentassem em seu aplicativo. / cc @fivetanley , @bryanhickerson , @revanar , @phammers , @scottmessinger , @ tharrington1 , @ manimis902 , @jakesjews , @ elwayman02. Informe se você vir alguma mensagem de afirmação não ideal em seu aplicativo.

Para experimentar, atualize seu bower.json para incluir a dependência ember da seguinte maneira:

{
  "name": "backtracking",
  "dependencies": {
    "ember": "intercom/ember#2.10.2-with-improved-backtracking-assertion",
    "ember-cli-shims": "0.1.3"
  },
  "resolutions": {
    "ember": "2.10.2-with-improved-backtracking-assertion"
  }
}

Você pode ver um exemplo de aplicativo executando esta compilação aqui: https://github.com/GavinJoyce/backtracking/pull/10

Acabei de cortar uma versão 1.11.0-canário

Isso é um erro de digitação?

@rwjblue obrigado, isso foi um erro de digitação. Atualizada

@GavinJoyce, obrigado por assumir isso! Tentei fazer isso em nosso aplicativo e é definitivamente _mais_ útil do que a mensagem anterior. Infelizmente para nós, isso ainda não torna muito fácil remediar esse problema porque a propriedade que ele observa como sendo modificada não está obviamente modificada em nenhum dos locais indicados pela mensagem de erro. Não tenho certeza do porquê, mas esperamos aprofundar mais no próximo ano.

@Dhaulagiri se você estiver interessado, compartilhamento de tela em algum momento e mergulhar no seu problema exato. Espero que as mensagens de erro sejam o mais úteis possível e seria útil considerar seu caso (e provavelmente poderei ajudar a identificar a causa raiz).

FWIW, encontrei outro problema relacionado a isso: https://github.com/alexspeller/ember-cli-active-link-wrapper/issues/25

Também tentei o branch de @GavinJoyce ao tentar encontrar um bug em um esforço contínuo para trazer um controle de abas para o ember-paper (PR referenciado acima). Infelizmente, parece que, no meu caso, também recebo referências a componentes que não parecem estar envolvidos.

@bjornharrtell , você tem um ramo de papel de brasa que eu possa experimentar?

^ Dedicamos um pouco de tempo para mergulhar nas questões do papel de brasa (https://github.com/miguelcobain/ember-paper/pull/590). Parece que:

  • as novas mensagens de erro foram mais úteis do que as atuais
  • eles não eram perfeitos, pois não lidavam bem com o conteúdo gerado. (o componente que continha {{yield}} foi relatado como a fonte que foi útil, mas não tão útil quanto poderia ser)

Pode ser ou não um bug do complemento, mas encontrei este erro em https://github.com/DockYard/ember-one-way-controls/issues/136

Eu encontrei um problema.
Estou usando um mixin que tem pontos de entrada para atualizar a mesma propriedade do controlador para o qual foi mixado. Essas são propriedades definitivamente diferentes porque simplesmente pertencem a controladores diferentes e a declaração falha e bloqueia js.
Eu testei o mixin desdobrando-o em alguns controladores e fiz uma transição entre as rotas para reproduzir - não foi reproduzido.

Por enquanto, estou tentando me livrar dos mixins, então simplesmente vou matá-los e criar uma solução alternativa.

Acredito ter um caso de uso válido em que estamos vendo esse problema de re-renderização. Em nosso aplicativo, temos um botão que contém algum estado (ok, validando, aviso, erro). É um componente que mostra o estado atual, valida quando certas coisas acontecem e, com base no resultado da validação ou ativação, exibe coisas diferentes (spinners, texto de botão diferente, classe de botão diferente).

Verificamos a validação em init() e, com base na resposta da validação, definimos o estado do botão apropriado. A classe de botão é uma propriedade computada que define as classes apropriadas com base no estado do botão. Como isso acontece no init, parece que esse erro está sendo disparado porque começamos com o status ok na instanciação, depois fazemos a transição para validar conforme validamos a versão e o estado final com base na resposta. No entanto, o caso de uso em si parece razoável e, portanto, as mudanças de estado que estão acontecendo também parecem razoáveis.

@ tundal45, você pode criar um twiddle ou aplicativo de amostra que demonstre o que você acredita ser um erro incorreto?

@ Blackening999 @ tundal45 você pode reduzir o seu caso de uso a uma confusão?

@chancancode @ Blackening999 Vou tentar postar um aqui em breve. Obrigado por uma resposta rápida.

@chancancode https://ember-twiddle.com/936d549b5625b0cf4f3c945d0ed04d3b?openFiles=components.button-with-state.js seria o twiddle, mas não estou vendo o erro que estou vendo no aplicativo, então pode ser alguma outra coisa que está causando isso.

Estou vendo isso em várias propriedades computadas, uma das quais é um simples Ember.computed.or . Visto que nenhuma das sugestões de @ manimis902 são aplicáveis ​​neste caso, qual seria uma solução alternativa apropriada?

Como @ tharrington1 menciona onde está o sinalizador para o recurso mencionado por @chancancode ?

@cbou , pelo que eu sei, essa bandeira não existe

Eu não tinha certeza de como lidar com esses avisos de depreciação, nem tenho certeza se minha correção era / é válida, mas estava fazendo uma solicitação AJAX no gancho do componente init() que acionou uma mudança de valor em um diferente propriedade do serviço (para rastrear / mostrar se estiver acessando o servidor remoto).

Mudei meu código de solicitação AJAX do gancho do componente init() para o gancho do componente didRender() e parece ter resolvido meu aviso de suspensão de uso.

@ lvl99 Eu fiz a mesma coisa.

Estamos nos esforçando para atualizar nosso projeto empresarial para o Ember 2.12 de 2.3. Em nosso projeto, temos um complemento de validação e um complemento de componentes de formulário separados. O complemento de validação funciona em Ember.components para gerar erros de validação e o complemento de componentes de formulário exibe os erros gerados pelo complemento de validação por meio de um auxiliar. Os add-ons são muito complicados para compartilhar o código-fonte; portanto, criamos o seguinte twiddle para ilustrar o caso que estamos enfrentando.

O exemplo fornecido contém dois componentes ( person-detail e address-detail ) que são responsáveis ​​por gerar seus próprios erros de validação. Os erros de validação gerados por address-detail são transmitidos em cascata ao componente contendo ( person-detail ) por meio da ação lançada dentro da propriedade computada errors . Os erros gerados por cada componente são exibidos em um componente error-displayer com a ajuda do auxiliar error-formatter . O código fornecido está funcionando conforme o esperado, como você pode ver.

Contudo; temos um aviso de suspensão de uso como segue: DEPRECATION: The error property ofis an Ember.Binding connected to validatable.errors.name , but Ember.Binding is deprecated. Consider using an alias computed property instead. [deprecation id: ember-metal.binding] See http://emberjs.com/deprecations/v2.x#toc_ember-binding for more details. Para evitar isso; por favor, vá para o auxiliar error-formatter e comente a linha número 9 e descomente a linha número 8 para que estejamos fazendo conforme sugerido na explicação do aviso.

Agora chegamos ao infame Assertion Failed: You modified "error" twice on <Ember.Object:ember338> in a single render. It was rendered in "component:error-displayer" and modified in "component:error-displayer". This was unreliable and slow in Ember 1.x and is no longer supported. See https://github.com/emberjs/ember.js/issues/13948 for more details. Entendemos por que estamos recebendo esse erro; porque a ação disparada dentro de address-detail s errors propriedade computada resulta no recálculo de errors propriedade computada de person-detail e o conteúdo que já foi renderizado está causando este erro . Aqui está o que gostaríamos de aprender:

  1. Ember.Binding vs Ember.computed.alias está funcionando de maneira bem diferente com certeza em termos de fase de recálculo (re-renderização). Qual é a diferença exata? Sugerir o uso do último como um substituto para o primeiro parece quebrar o código; pelo menos para o nosso caso.
  2. O disparo de uma ação de dentro de uma propriedade computada é um problema? Se sim; quais são as sugestões possíveis para evitá-lo?
  3. Estamos considerando acionar a ação de empacotamento com uma instrução Ember.run.scheduleOnce('afterRender', ...) . Este é o caminho certo a seguir?
  4. Finalmente; por favor, volte a quebrar o código e digite algo em qualquer campo; e, surpreendentemente, os componentes são renderizados novamente várias vezes; suspeitamos que isso possa estar relacionado a um bug.

FWIW, eu vi meus componentes sendo renderizados com mais frequência do que eu esperaria em alguns casos. Rastrear a causa de um rerender consome muito tempo porque geralmente é sincronizado com um runloop. Adoraria saber se existem atalhos ou truques de depuração nesta área.

Existe uma maneira de capturar ou suprimir essa afirmação em compilações de depuração? Rastreamos e corrigimos isso por meio de refatores, conforme descrito acima, na maioria dos lugares, mas há 1 ou 2 que são bastante teimosos. Em um caso particular, estamos destruindo um objeto e, em seguida, fazendo a transição. O objeto destruído (em nossa API) envia uma notificação pusher para descarregar / destruir vários outros objetos.

Em builds de produção, a re-renderização não é um problema, já que estamos apenas destruindo o objeto e, em seguida, fazendo a transição de qualquer maneira (assim, toda a rota está sendo demolida). No entanto, a afirmação sobre as compilações de desenvolvimento é bastante frustrante, pois requer uma atualização para restaurar o site. Eu entendo por que estamos obtendo o erro, mas é um refatorador bastante complicado neste caso para evitá-lo e, em qualquer caso, não importa, já que toda a rota está sendo destruída. Existe uma maneira de detectar / suprimir / alterar isso para um aviso? Eu tentei um try / catch, bem como o manipulador de erros da rota, mas não peguei.

@ feanor07 enviando uma ação de dentro de get que invalida a propriedade a que já foi renderizada é o fluxo de retorno de dados, antes que as ligações com um ciclo detectassem e selecionassem silenciosamente a direção para frente como a vencedora, mas isso tem um grande custo se isso fluir várias coisas e flui de volta para a fonte.

Basicamente, você tem uma dependência cíclica e precisa que os dados fluam, não processe o erro antes de executar a validação. Você pode validar em um componente pai que produza o modelo e erros para renderizar o formulário dentro de seu bloco.

@ feanor07 Ember.run.scheduleOnce... não funcionou, mas adicionar apenas um Ember.run.schedule("afterRender", () => { ... }); à propriedade set indicada primeiro pelo rastreamento de pilha eliminou muitas mensagens de erro que caíram em cascata após a inicial.

@neilthawani que pode ocultar o erro, mas não necessariamente corrige o problema. O erro indica que você está definindo um valor duas vezes, quando provavelmente deveria defini-lo apenas uma vez. Ao colocar um dos set em schedule , você está apenas atrasando o segundo conjunto para que aconteça em um loop de execução diferente. Você não corrigiu o problema principal de renderizar duas vezes quando você só precisa renderizar uma vez, apenas enganou o Ember para que não soubesse que havia um problema, porque agora as renderizações acontecem em runloops separados.

@ elwayman02 Uh oh. Obrigado. Basicamente, errou totalmente o ponto.

Edit: Depois de lutar com isso, eu inseri mais afterRenders que eu estava confortável. Temos um manipulador click em um de nossos componentes de viz de dados que alterna uma dica de ferramenta. Definir o sinalizador isDisplaying dentro de Ember.run.schedule("afterRender", () => { ... }); nos permitiu depurar o problema real, que na verdade foi um retrocesso no controlador invocando o componente de visualização de dados e o componente de dica de ferramenta.

tl; dr: Eu não o mantive lá (também recebi um erro Maximum call stack size exceeded uma vez), mas usá-lo foi útil para depurar até que o problema real fosse descoberto.

PSA para qualquer um que esteja atualizando agora: O erro de asserção aprimorado "retrocesso de renderização" mencionado por @GavinJoyce acima está na verdade incluído no Ember 2.11. Também foi sugerido que pular direto para 2.11 pode ser útil.

Pessoal, preciso de ajuda: Esse erro aparece quando tento usar uma propriedade de modelo que "pertence a" outra. Criei um projeto em branco e ainda mostra a mesma coisa. O que estou fazendo de errado?

Além disso, no meu back-end, estou usando .Net Core com JSON API .Net Core (https://github.com/Research-Institute/json-api-dotnet-core) - seguindo suas instruções.

A renderização da IU está quebrada neste ponto, no entanto, os dados são carregados e posso ver os valores desejados.

    // Profile Model:
    import DS from 'ember-data';
    export default DS.Model.extend({
        'firstName': DS.attr(),
        'lastName': DS.attr(),
        'applicationUser': DS.attr(),
        'contactProfile': DS.belongsTo('address', {
            async: true
        }),
        'companyProfile': DS.belongsTo('address'),
        'companyMailingAddress': DS.belongsTo('address'),
        "companyPhysicalAddress": DS.belongsTo('address')
    });

    // Address Model:
    import DS from 'ember-data';
    export default DS.Model.extend({
        'address1': DS.attr(),
        'address2': DS.attr(),
        'city': DS.attr(),
        'state': DS.attr(),
        'zipCode': DS.attr(),
        'country': DS.attr(),
        'website': DS.attr(),
        'phoneNumber1': DS.attr(),
        'phoneExtension1': DS.attr(),
        'phoneNumber2': DS.attr(),
        'phoneExtension2': DS.attr(),
        'email': DS.attr(),
    });
    // Adapter settings
    import DS from 'ember-data';

    export default DS.JSONAPIAdapter.extend({
        namespace: 'api/json',
    });
    DS.JSONAPISerializer.reopen({
        keyForAttribute(key) {
            return key;
        },
        keyForRelationship(key) {
            return key;
        }
    });
    // Route
    import Ember from 'ember';

    export default Ember.Route.extend({
        model() {
            return Ember.RSVP.hash({
                profile: this.store.findRecord('profile', 1)
            });
        }
    });

    // Template
   {{model.profile.contactProfile.address1}}

e o erro que recebo:
Falha na declaração: você modificou "model.profile.contactProfile" duas vezes em@model: profile :: ember543: 1> em uma única renderização. Ele foi renderizado em " template: fuels-ember / internal / profile / template.hbs " e modificado em " template: fuels-ember / internal / profile / template.hbs ". Isso não era confiável e lento no Ember 1.xe não é mais compatível. Consulte https://github.com/emberjs/ember.js/issues/13948 para obter mais detalhes.

PS: Tentei usar o método Ember.computed para obter a propriedade e parece funcionar. Isso é necessário?

Atualização: também descobri que os dados carregam muito bem dentro de um auxiliar {{#each}}, mas não diretamente no modelo.

@lbarsukov
Talvez esteja relacionado a https://github.com/emberjs/data/issues/5023, onde uma retrocesso de renderização é causada por relacionamentos em sua resposta jsonapi com um conjunto de propriedades links .

Esse foi o problema para mim, que começou depois do Ember Data 2.13.2. Tente usar ember-data: 2.13.2 para ver se isso resolve o seu problema.

@daniel-de-wit Perfeito para o mestre aqui - isso realmente funciona. Agora faz o que preciso e estou feliz com isso.

@lbarsukov @ daniel-de-wit Lançamos uma nova versão do ember data que corrige esse problema.

@lbarsukov Acho que isso tem a ver com seus relacionamentos definidos. Há uma boa chance de um (ou alguns) dos belongsTo ser hasMany .

Digamos que você tenha dois modelos, pergunta e resposta. Se você retornar 10 respostas para a pergunta, mas cada serializador de pergunta se referir à sua resposta, você _terá_ que definir o relacionamento corretamente.

// Question Model:
    export default DS.Model.extend({
        'answers': DS.hasMany('answers'), // if you never reference question.answers you can omit this
        ...
    });

// Answer Model:
    export default DS.Model.extend({
        'question': DS.belongsTo('question'),
        ...
    });

Quando os dados definem vários pares de pergunta / resposta, esperando um relacionamento 1-1 onde não existe, ele infere que a pergunta foi modificada no meio da renderização.

Da postagem inicial, alguns ganchos foram mencionados:

Este é um exemplo bastante extremo, mas ilustra o problema. Além de init, didInitAttrs, didReceiveAttrs, willInsertElement e willRender também acontece de forma síncrona durante o processo de renderização. Além disso, o retrocesso costuma ser um problema decorrente do comportamento de propriedades vinculadas bidirecionais.

Por que os ganchos didInsertElement e didRender funcionando perfeitamente, mas os outros ganchos falham com o erro twice render ?

@BenjaminHorn @ Blackening999 @Dhaulagiri @DingoEatingFuzz @ Gaurav0 @GavinJoyce @Redsandro @TRMW @ Turbo87 @aklkv @alidcastano @backspace @bdiz @bgentry @bjornharrtell @bryanhickerson @buschtoens @buschtoens @casekana -limcbley @dhanhickerson @buschtoens @casekana -limcira -de- limira -de- cibira @ dhano- civira @buschtoens witkana -de- limira -de- limira- civira @buschtoens @ civira. @fotinakis @gabrielgrant @ghost @jakesjews @janmisek @joukevandermaas isso ainda é um problema, talvez devêssemos encerrar, o que você acha?

Corrigi todas as instâncias do erro em meu aplicativo.

Sempre que encontro isso, consigo reorganizar as coisas para que não aconteça mais, então acho que não há problema em encerrar.

Sim feche por favor

fim de uma era 😬

👍

Desculpe levantar um problema antigo.

Digamos, por exemplo, que estou renderizando

{{this.myBool}}

e o erro é Error: Assertion Failed: You modified "myBool" twice

Posso corrigir o erro alterando-o para:

{{if this.myBool true false}}

Da mesma forma, se uma ligação de nome de classe está causando o problema

Eu posso mudar:

classNameBindings: ['myBool']

para

classNameBindings: ['myBool:yes:no']

Se eu posso silenciar o aviso assim, por que Ember não pode lidar com isso por mim?

Aqui está o código de demonstração que eu estava usando:

https://ember-twiddle.com/db7f6e382bd0b1de91447881eebb62a5?openFiles=templates.components.my-component.hbs%2C

Nenhuma dessas coisas “corrige” o problema. É que você mudou para o modo de produção ou há bugs no código de asserção / detecção. Em qualquer caso, você precisa corrigir o lado que atribui / define o valor, não o lado que o consome.

OK. Obrigada. Eu entendo o problema de retrocesso descrito nesta postagem original porque tem um set explícito

Mas no meu twiddle de demonstração, não há set até onde posso ver.

_Editar_ Isso saiu errado, quero dizer que não há set vindo de uma parte _subsequente_ do modelo como há no exemplo

Hm, não estou recebendo o erro no twiddle, qual é a sequência de cliques que devo fazer?

Clique em abrir e em fechar. Mas o botão Fechar do componente filho gerado, não o pai.

Eu vejo, o problema é que durante a desmontagem, focusOut é chamado no componente que chama set em uma propriedade já renderizada. Não estou 100% certo de como o componente perde o foco e a semântica do tempo. Tenho certeza de que as variações que você tentou apenas confundem o sistema de rastreamento e mascaram o problema subjacente. Vamos rastrear isso em uma nova edição? Não tenho certeza se é um problema válido, mas vamos fazer a investigação lá.

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