by Jonathan Puc
乔纳森·普克(Jonathan Puc)
我如何使用React,Redux-Saga和Styled Components构建NBA球员资料获取器 (How I built an NBA player profile fetcher with React, Redux-Saga, and Styled Components)
Hello, all! It’s been a while since I built something out of personal enjoyment or curiosity, so I surfed the internet exploring cool API’s.
大家好! 自从我出于个人乐趣或好奇心建立东西以来已经有一段时间了,所以我上网浏览了很酷的API。
Since it’s NBA Playoff time (sadly, I’m a Knicks fan), I decided to see if there was an existing API that contained the data of every player currently in the NBA — and heck yeah, there was.
由于现在是NBA季后赛的时间(很遗憾,我是尼克斯的球迷),所以我决定查看是否存在一个包含NBA当前每个球员的数据的API-确实如此。
Also, a project I’m working on at my job has introduced me to two awesome libraries called redux-saga and styled components. They are pretty darn exciting, and are two things I definitely plan to try and use in all my future projects.
另外,我正在工作的一个项目将我介绍给了两个很棒的库,分别称为redux-saga和styled components 。 它们非常令人兴奋,是我绝对计划在以后的所有项目中尝试使用的两件事。
So let’s build a React application with these libraries!
因此,让我们使用这些库构建一个React应用程序!
Before we dive in, let’s just talk a bit about redux-saga and styled components and why they are handy.
在深入探讨之前,让我们先讨论一下redux-saga和样式化的组件以及它们为什么方便使用。
Redux-Saga (Redux-Saga)
In Redux, actions and reducers are pure, meaning they don’t have any side effects.
在Redux中,动作和减速器是纯净的,这意味着它们没有任何副作用。
An example of a side-effect could be something like a service request. When you are making a request, it can fail or return a different kind of result even though you always send the same request.
副作用的一个例子可能是服务请求之类的东西。 当您发出请求时,即使您始终发送相同的请求,它也可能失败或返回不同类型的结果。
So if your reducers and actions are pure, where can you handle / put side effects? Well redux-saga is a solution. It allows you to listen to actions, perform a side effect, and then dispatch another action.
因此,如果您的减速器和动作是纯净的,那么在哪里可以处理/放置副作用? 那么redux-saga是一个解决方案。 它使您可以收听动作,执行副作用,然后分派另一个动作。
I know, talk is cheap. Show me the code.
我知道,谈话很便宜。 给我看代码。
Are you ready to see an example of this beast at work?
您准备好在工作中看到这种野兽的例子吗?
In a nutshell, we have a function that listens for whenever an action of type ‘IMAGE_FETCH_REQUESTED’
is dispatched. When it identifies one, it’ll call the fetchImage function.
简而言之,我们有一个函数,该函数在调度'IMAGE_FETCH_REQUESTED'
类型的动作时侦听。 当识别出一个时,它将调用fetchImage函数。
Inside the fetchImage function, we simply make a special call
to a method on our service
object, passing along the userId
of the profile image we want to grab. The result gets saved inside our profileImage variable.
在fetchImage函数内部,我们只需对service
对象上的方法进行特殊call
,并传递我们要获取的配置文件图像的userId
。 结果将保存在我们的profileImage变量中。
Shortly after, we let our store know that we have successfully grabbed an image and would like to pass the image on to be stored. So we’ll just dispatch an action with put
with the type of 'IMAGE_FETCH_SUCCEEDED'
and pass the image as payload. Our reducer will handle the rest.
不久之后,我们通知商店我们已成功获取图像,并希望将图像传递给存储。 因此,我们将使用类型为'IMAGE_FETCH_SUCCEEDED'
put
调度一个动作, put
图像作为有效负载传递。 我们的减速机将处理其余的工作。
But if there is some kind of error, we simply dispatch an action with the type'IMAGE_FETCH_FAIL'
and pass the error as payload.
但是, 如果存在某种错误,我们只需调度类型为'IMAGE_FETCH_FAIL'
,并将错误作为有效负载传递。
The beauty of it lies in how nicely it reads and sits within a simple try catch block.
它的优点在于它在一个简单的try catch块中的读取和放置效果很好。
Feel free to read more about redux-saga.
随时阅读有关redux-saga的更多信息。
样式化的组件 (Styled Components)
Discovering styled components kind of blew my mind.
发现样式化的组件让我大吃一惊。
I always had trouble structuring and writing CSS inside React apps. Something didn’t sit right and it felt messy to me. In particular, class names were tough.
我在React应用程序内部构造和编写CSS时总是遇到麻烦。 东西坐不对劲,这让我感到混乱。 特别是,类名很难。
The whole idea of React is about being modular: you write a component once and are able to use it everywhere. But when styling such components, we still give them a class name to target them with CSS.
React的整个思想都是关于模块化的:您只需编写一次组件就可以在任何地方使用它。 但是在样式化这些组件时,我们仍然给它们一个类名 使用CSS定位它们。
Max Stoiber, co-creator of styled components, put it perfectly when he said:
样式组件的共同创建者Max Stoiber完美地说:
If you only ever use every class name once, why do you have a class name at all?
如果您一次只使用每个类名,那么为什么要一个类名呢?
Having heard those words, I knew styled components was for me.
听到了这些话,我知道样式化组件适合我。
So let’s see this one at work now too:
因此,让我们现在也来看一下它:
Here we have a basic functional component: a button that pretty much does nothing, even though it’s daring you to make your move.
在这里,我们有一个基本的功能组件:一个按钮,几乎不执行任何操作,即使它敢于让您行动起来。
This may look weird to newcomers, but really it’s quite simple and I’m sure you’ll fall in love with it in no time.
对于新来者来说,这可能看起来很奇怪,但实际上这很简单,我敢肯定,您很快就会爱上它。
We import styled
from the library. Think of this as a factory that allows you to create the HTML nodes you all know and love.
我们从库中导入styled
。 可以将其视为一个工厂,它允许您创建大家都知道并喜欢HTML节点。
We create the node of our liking. In this case, a button and span, with its styles. We then assign it to a variable of our choice.
我们创建自己喜欢的节点。 在这种情况下,为按钮和跨度及其样式。 然后,将其分配给我们选择的变量。
Now we refer to those variables and pop them within our functional component to be rendered.
现在,我们引用这些变量并将它们弹出到要呈现的功能组件中。
It’s as easy as that.
就这么简单。
What I really like is that you can still write the CSS you are familiar with in a JS file. Furthermore, it keeps everything nice and modular — everything sits within a single file, easy to read and digest!
我真正喜欢的是,您仍然可以在JS文件中编写熟悉CSS。 此外,它使所有内容保持良好和模块化-所有内容都位于一个文件中,易于阅读和消化!
You can learn more about styled-components here.
您可以在此处了解有关样式化组件的更多信息。
所有这些如何联系在一起 (How this all links together)
We’ll be building an application where users can search for a player using their first and last name. Our saga (redux-saga) will fetch the data of the player, including statistics and a headshot of them, and save it into our redux store. And using styled components, we’ll make all this information look a little more presentable.
我们将构建一个应用程序,用户可以在其中使用其名字和姓氏搜索球员。 我们的传奇(redux-saga)将获取播放器的数据,包括统计数据和爆头,并将其保存到我们的redux存储中。 并使用样式化的组件,我们将使所有这些信息看起来更具表现力。
第1部分-设置我们的应用程序和react-redux。 (Part 1 — Setting up our app and react-redux.)
We’ll be using create-react-app in this project, so if you haven’t yet got it installed, just run npm install -g create-react-app
.
我们将在此项目中使用create-react-app,因此,如果尚未安装,请运行npm install -g create-react-app
。
When that’s done, we’ll run create-react-app nba-players
.
完成后,我们将运行create-react-app nba-players
。
Now after all the installing and scaffolding is done, we’ll cd nba-players
and then install the modules we’ll need with npm install --save redux react-redux redux-saga styled-components axios
.
现在,在完成所有安装和脚手架之后,我们将对cd nba-players
,然后使用npm install --save redux react-redux redux-saga styled-components axios
安装所需的模块。
设置我们的redux商店 (Setting up our redux store)
This will be a quick walkthrough of getting our store set up, since this guide is about redux-saga and styled components and not about react-redux/redux.
这将是建立商店的快速指南,因为本指南是关于redux-saga和样式化组件的,而不是react-redux / redux。
Inside your src
folder, we’ll create a folder called store
and create our index.js
file.
在您的src
文件夹中,我们将创建一个名为store
的文件夹并创建我们的index.js
文件。
store/index.js
商店/index.js
We’ll be using Redux DevTools to see what’s going on under the hood in our store. You can download the Chrome extension here.
我们将使用Redux DevTools来查看我们商店内部的动态。 您可以在此处下载Chrome扩展程序。
让我们创建我们的减速器。 (Let’s create our reducers.)
Make a folder called reducers
within the root of your store
folder, and create the two following files:
在store
文件夹的根目录中创建一个名为reducers
的文件夹,并创建以下两个文件:
reducers/index.js
reducers / index.js
reducers/player.js
reducers / player.js
让我们创造行动 (Lets create our actions)
Make a folder called actions
within the root of your store
folder, and create the two following files:
在store
文件夹的根目录中创建一个名为actions
的文件夹,并创建以下两个文件:
actions/actionTypes.js
actions / actionTypes.js
actions/player.js
动作/player.js
With all those pieces created, let’s connect the store to our React application!
创建所有这些片段后,让我们将商店连接到我们的React应用程序!
Navigate your way to src/index.js
and add the following:
导航至src/index.js
并添加以下内容:
Sweet, let’s test and make sure everything is working as expected.
亲爱的,让我们进行测试并确保一切都按预期进行。
Back in our terminal, we’ll run npm run start
to fire up our React app, open the developer tools, and navigate to the ‘Redux’ tab. Click on the State tab within the Redux DevTools.
回到我们的终端,我们将运行npm run start
来启动我们的React应用程序,打开开发人员工具,并导航到“ Redux”标签。 单击Redux DevTools中的“状态”选项卡。
You should see something like this :)
您应该看到类似这样的内容:)
Awesome, we’ve got everything we need to get started.
太棒了,我们已经具备了开始所需的一切。
第2部分-Redux Saga (Part 2— Redux Saga)
We’re ready to utilise the NBA player API to fetch data and load it into our store!
我们已经准备好利用NBA Player API来获取数据并将其加载到我们的商店中!
Let’s write our first saga.
让我们来写我们的第一个传奇。
Inside our src/store
folder, we’ll create a folder called sagas
and create a file called index.js
.
在src/store
文件夹中,我们将创建一个名为sagas
的文件夹,并创建一个名为index.js
的文件。
This basically serves as our watcher / gatekeeper.
这基本上是我们的观察者/网守。
Line 8
sits there and listens for certain action types we give it. When an action passes through that matches, it’ll call a function, in this case retrievePlayer. We’ll create that now.
Line 8
坐在那里,听我们给出的某些动作类型。 当某个动作通过匹配项时,它将调用一个函数,在本例中为retrievePlayer。 我们现在将创建它。
Within the same folder, we’ll create a file called player.js
and it’ll contain the following:
在同一文件夹中,我们将创建一个名为player.js
的文件,其中包含以下内容:
The retrievePlayer generator function is where the magic happens, so let’s walk through it.
神奇的地方就是retrievePlayer生成器功能,因此让我们逐步进行了解。
The function has access to the action that’s passed through. If you can recall from our action creator in actions/player.js
, we pass a name.
该函数可以访问通过的操作。 如果您可以在actions/player.js
从动作创建者actions/player.js
,那么我们会传递一个名称。
We’ll use ES6 destructuring to get the name and surname from the name object attached to the action payload.
我们将使用ES6解构从附加到动作有效内容的名称对象中获取名称和姓氏。
Using redux-saga, we call
our fetchPlayerData function and pass in the name details.
使用redux-saga,我们call
fetchPlayerData函数并传递名称详细信息。
fetchPlayerData will make a GET call to the NBA players API and return the response. The response will be saved inside the stats variable.
fetchPlayerData将对NBA球员API进行GET调用并返回响应。 响应将保存在stats变量中。
Access to the players image is as easy as appending the name and surname to the API endpoint, so we do just that.
访问播放器图像就像将名称和姓氏附加到API端点一样容易,因此我们就可以做到这一点。
We save our two new pieces of data into an object called playerProfile.
我们将两个新数据保存到名为playerProfile的对象中。
We then use redux-saga’s put which will dispatch an action. Here we give it the type of GET_PLAYER_SUCCESS
with the our new playerProfile as the payload.
然后,我们使用redux-saga的put来调度动作。 在这里,我们将其类型GET_PLAYER_SUCCESS
,并将新的playerProfile作为有效负载。
If something goes wrong, we simply dispatch an action with the type GET_PLAYER_FAIL
and pass the error as the payload.
如果出了什么问题,我们只需调度一个类型为GET_PLAYER_FAIL
的动作,并将错误作为有效负载传递。
That’s it!
而已!
Our players reducer that we made previously at reducers/player.js
will handle the rest after receiving the actions we dispatched.
我们先前在reducers/player.js
制作的玩家reducer将在收到我们分派的动作后处理其余的事情。
There is one last thing we need to do before our sagas work, however.
但是,在进行Sagas工作之前,我们需要做的最后一件事。
Inside store/index.js
we’ll have to make some modifications.
在store/index.js
内部,我们必须进行一些修改。
It should now look like the following
现在应该如下所示
Woohoo, we’re now ready to build some components that’ll allow us to search for a player and see their image and stats :)
Woohoo,我们现在准备构建一些组件,使我们可以搜索播放器并查看其图像和统计信息:)
第3部分-样式化的组件 (Part 3 — Styled Components)
components/Search.js
components/Search.js
components/StatBox.js
components/StatBox.js
components/PlayerPhoto.js
components/PlayerPhoto.js
components/Player.js
components/Player.js
With all our components built, it’s time to import them into our App.js
构建了我们所有的组件之后,是时候将它们导入到我们的App.js
Everything’s hooked up and ready to go. Simply type in the full name of a player to your liking, such as Lebron James or Stephen Curry, and you should see something like this.
一切都已准备就绪,可以开始使用了。 只需输入您喜欢的球员的全名,例如勒布朗·詹姆斯或斯蒂芬·库里,您应该会看到类似的内容。
Not the prettiest thing to look at, but this is an opportunity for you to apply styling as you see fit. Go crazy with the styled-components library.
并不是最漂亮的东西,但这是您有机会让您应用自己认为合适的样式的机会。 使用样式化的组件库疯狂。
Also remember that we added a loading
property in our redux store state.player.loading
? Why not make the UX a little bit nicer by showing a loading message of some kind when loading is set to true?
还记得我们在redux存储state.player.loading
添加了loading
属性吗? 为什么在加载设置为true时通过显示某种类型的加载消息来使UX更好一点?
We’ve created the foundation of the application together — now go on and give it your own personal touch :)
我们一起创建了应用程序的基础-现在继续进行操作,让您自己拥有个性:)
If needed, you can find the source code here.
如果需要,可以在此处找到源代码。
As always, my inbox is open to anybody in need of further advice or if you have questions.
与往常一样,我的收件箱向所有需要进一步建议或有任何疑问的人开放。
Feel free to connect with me on any of the platforms below!
随时在以下任何平台上与我联系!
Instagram | LinkedIn | Twitter
Instagram | 领英 推特
翻译自: https://www.freecodecamp.org/news/build-a-nba-player-profile-fetcher-with-react-redux-saga-and-styled-components-680cde2b8254/