天天看點

資料驅動——元件

hard-coding data in our applications isn't exactly ideal.

today, we'll set up our components to be driven by data to them access to external data.

through this point, we've written our first components and set them up in a child/parent relationship.

however, we haven't yet tied any data to our react components. although it's a more pleasant experience (in our opinion) writing a website in react, we haven't taken advantage of the power of react to display any dynamic data.

資料驅動——元件

 we broke down our demo into components and ended up building three separate components with static jsx templates.

it's not very convenient to have to update our component's template everytime we have a change in our website's data.

instead, let's give the components data to use to display.

let's start with the ​<code>​&lt;header /&gt;​</code>​ component. as it stands right now, the ​<code>​&lt;header /&gt;​</code>​ component only shows the title of the element as ​<code>​timeline​</code>​. it's a nice element and it would be nice to be able to reuse it in other parts of our page, but the title of ​<code>​timeline​</code>​ doesn't make sense for every use.

let's tell react that we want to be able to set the title to something else.

react allows us to send data to a component in the same syntax as html, using attributes or properties on a component.

this is akin to passing the ​<code>​src​</code>​ attribute to an image tag. we can think about the property of the ​<code>​&lt;img /&gt;​</code>​ tag as a ​<code>​prop​</code>​ we're setting on a component called ​<code>​img​</code>​.

we can access these properties inside a component as ​<code>​this.props​</code>​. let's see ​<code>​props​</code>​ in action.

舊:

when we use the ​<code>​&lt;header /&gt;​</code>​ component, we placed it in our ​<code>​&lt;app /&gt;​</code>​ component as like so:

資料驅動——元件

新:

we can pass in our ​<code>​title​</code>​ as a prop as an attribute on the ​<code>​&lt;header /&gt;​</code>​ by updating the usage of the component setting the attribute called ​<code>​title​</code>​ to some string, like so:

inside of our component, we can access this ​<code>​title​</code>​ prop from the ​<code>​this.props​</code>​ property in the ​<code>​header​</code>​ class. instead of setting the title statically as ​<code>​timeline​</code>​ in the template, we can replace it with the property passed in.

we've also updated the code slightly to get closer to what our final ​<code>​&lt;header /&gt;​</code>​ code will look like, including adding a ​<code>​searchicon​</code>​ and a few elements to style the ​<code>​menuicon​</code>​.

now our ​<code>​&lt;header /&gt;​</code>​ component will display the string we pass in as the ​<code>​title​</code>​ when we call the component. for instance, calling our ​<code>​&lt;header /&gt;​</code>​ component four times like so:

results in four ​<code>​&lt;header /&gt;​</code>​ components to mount like so:

資料驅動——元件

pretty nifty, ey? now we can reuse the ​<code>​&lt;header /&gt;​</code>​ component with a dynamic ​<code>​title​</code>​ property.

we can pass in more than just strings in a component.

we can pass in numbers, strings, all sorts of objects, and even functions!

we'll talk more about how to define these different properties so we can build a component api later.

instead of statically setting the content and date let's take the ​<code>​content​</code>​ component and set the timeline content by a data variable instead of by text.

just like we can do with html components, we can pass multiple ​<code>​props​</code>​ into a component

as we did with ​<code>​title​</code>​, let's look at what ​<code>​props​</code>​ our ​<code>​content​</code>​ component needs:

a user's avatar image

a timestamp of the activity

text of the activity item

number of comments

let's say that we have a javascript object that represents an activity item.

we will have a few fields, such as a string field (text) and a date object. we might have some nested objects, like a ​<code>​user​</code>​ and ​<code>​comments​</code>​. for instance:

just like we passed in a string title to the ​<code>​&lt;header /&gt;​</code>​ component, we can take this activity object and pass it right into the ​<code>​content​</code>​ component.

let's convert our component to display the details from this activity inside it's template.

in order to pass a dynamic variable's value into a template, we have to use the template syntax to render it in our template. for instance:

we've use a little bit of es6 in our class definition on the first line of the ​<code>​render()​</code>​ function called destructuring. the two following lines are functionally equivalent:
destructuring allows us to save on typing and define variables in a shorter, more compact way.

we can then use this new content by passing in an object as a prop instead of a hard-coded string. for instance:

資料驅動——元件

 fantastic, now we have our activity item driven by an object.

however, you might have noticed that we would have to implement this multiple times with different comments.

instead, we could pass an array of objects into a component.

let's say we have an object that contains multiple activity items:

we can rearticulate our usage of ​<code>​&lt;content /&gt;​</code>​ by passing in multiple activities instead of just one:

however, if we refresh the view nothing will show up!

we need to first update our ​<code>​content​</code>​ component to accept multiple activities.

as we learned about previously, jsx is really just javascript executed by the browser. we can execute javascript functions inside the jsx content as it will just get run by the browser like the rest of our javascript.

let's move our activity item jsx inside of the function of the ​<code>​map​</code>​ function that we'll run over for every item.

資料驅動——元件

 now we can pass any number of activities to our array and the ​<code>​content​</code>​ component will handle it,

however if we leave the component right now, then we'll have a relatively complex component handling both containing and displaying a list of activities.leaving it like this really isn't the react way.

here is where it makes sense to write one more component to contain displaying a single activity item and then rather than building a complex ​<code>​content​</code>​ component,

we can move the responsibility.

this will also make it easier to test, add functionality, etc.

let's update our ​<code>​content​</code>​ component to display a list of ​<code>​activityitem​</code>​ components (we'll create this next).

not only is this much simpler and easier to understand, but it makes testing both components easier.

with our freshly-minted ​<code>​content​</code>​ component, let's create the ​<code>​activityitem​</code>​ component.

since we already have the view created for the ​<code>​activityitem​</code>​, all we need to do is copy it from what was our ​<code>​content​</code>​ component's template as it's own module.

資料驅動——元件

this week we updated our components to be driven by data by using the react ​<code>​props​</code>​ concept.