da2k / curso-reactjs-ninja

915 stars 322 forks source link

M3 A90: dispatch short notation (mapDispatchToProps: fetchVideos VS. registerVideo) #495

Closed pamplonapaulo closed 4 years ago

pamplonapaulo commented 4 years ago

Mestre @fdaciuk ,

https://github.com/da2k/curso-reactjs-ninja/tree/master/examples/m03/samples/49-reactflix/14

A respeito das abreviações/ short notations, estou tentando entender direito quando podemos mesmo lançar mão dessas abreviações. No final da aula 90 do M3, você aborda isso no caso do

dispatch(fetchVideos)

O nosso map estava:

        const mapDispatchToProps = (dispatch) => ({
          fetchVideos: () => dispatch(fetchVideos())
        })

Não quero abordar o desfecho final, onde a propriedade e seu valor são homônimos, daí a gente chega naquela simples { fetchVideos }. Isso já entendi.

Mas quando você do bloco acima avança para essa escrita:

        const mapDispatchToProps = {
          fetchVideos: fetchVideos
        }

Meu entendimento final é de que isso só é possível assim porque esse dispatch não está esperando nenhum parâmetro. Você fala isso com outras palavras, pelo que entendi.

E revisitando outros dispatchs do nosso código, e seus maps, vemos situações diferentes onde você manteve a call convencional do dispatch(). Se entendi corretamente, justamente porque nestes casos os parâmetros são fundamentais. Por exemplo:

export const registerVideo = ({ id, title }) => async (dispatch) => {
  await db.ref('videos').child(id).update({ id, title })
  dispatch(addVideo({ id, title }))
}

Acima, id e title são aguardados. Então ao chamar esse dispatch o código de register-video.js ficou "mais verboso":

await dispatch(registerVideo({ id, title }))

Esse raciocínio está correto? Sempre que não esperar parâmetros, posso fazer o dispatch sem escrever 'dispatch'?

Me impressionou um pouco que isso funcione. Só consigo crer que assim seja porque o { connect } deve saber exatamente o que fazer com aquilo que recebe no seu segundo parâmetro, aplicando por si o dispatch, com ou sem o nosso excesso de verbo.

É isso? rs

Abração e obrigado!

fdaciuk commented 4 years ago

Oi @pamplonapaulo! Vamos lá :)

Não quero abordar o desfecho final, onde a propriedade e seu valor são homônimos, daí a gente chega naquela simples { fetchVideos }. Isso já entendi.

Perfeito, podemos seguir daqui então :)


Esse raciocínio está correto? Sempre que não esperar parâmetros, posso fazer o dispatch sem escrever 'dispatch'?

Na verdade não, são coisas diferentes. Em um código, você está criando uma action creator, que vai ser assíncrona. Como ela vai ser assíncrona, no momento em que acontecer o dispatch dessa action, ela não pode simplesmente já mandar os dados para o reducer. Existe um processamento que precisa ser feito antes. Por isso, nesse código aqui:

export const registerVideo = ({ id, title }) => async (dispatch) => {
  await db.ref('videos').child(id).update({ id, title })
  dispatch(addVideo({ id, title }))
}

Nós temos uma função que retorna outra função. A primeira função vai receber os argumentos necessários para disparar a ação. Mas como a ação é assíncrona, nós retornamos uma segunda função, que vai receber o dispatch, para que o dispatch "real" da ação seja feito dentro dessa função registerVideo.

Nesse tipo de action creator, você sempre vai precisar disparar o dispatch quando for o momento de salvar os dados no Redux.

Agora, lá no caso do mapDispatchToProps, nós temos um caso especial: nós podemos criá-lo da seguinte forma:

const mapDispatchToProps = {
  fetchVideos: fetchVideos
}

pois especialmente essa função (mapDispatchToProps) é passada para o connect. E lá dentro do connect ele faz a seguinte verificação:

São basicamente dois momentos diferentes: o disparo da ação pelo mapDispatchToProps só acontece quando a função passada via props é executada dentro do componente.

Aí, se a action creator (que é a função que vai ser disparada), estiver retornando um objeto, então esse objeto vai ser a action passada para o reducer.

Já se essa função retornar uma outra função (action creator assíncrona), o código não chega ainda no Reducer. Ele fica parado ali até que a ação assíncrona termine, e o dispatch passada via argumento na segunda função seja executado.

Não é algo simples de explicar mesmo. Parece um processo muito complexo e absurdo, mas nada mais é do que funções e objetos sendo passados como argumento para outras funções, e referências de objetos sendo usados para disparar código no futuro :)

Por isso a importância de uma boa base de JS antes de pegar qualquer biblioteca: isso é intrínseco na linguagem, e precisa estar na ponta da língua. Se ainda não está, continue os estudos até entender, pois é um conceito muito importante a se aprender.

Continue estudando, praticando, testando formas diferentes de fazer. Mude o código e deixe rolar os erros. Leia os erros e tente entendê-los, depois volte e resolva.

Essa prática é que vai te trazer domínio da linguagem :)

Se não ficou muito claro a explicação acima, me avise que eu tento explicar de alguma outra forma, mas é importante que você entenda :)