- Components and Props: https://reactjs.org/docs/components-and-props.html
- Lifting state up to parent components: https://reactjs.org/docs/lifting-state-up.html
- Handling events (read til
Passing Arguments to Event Handlers) https://reactjs.org/docs/handling-events.html
- https://reactjs.org/docs/conditional-rendering.html
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Short-circuit_evaluation
- Container will contain ALL the state and eventhandlers (handleOnClick, handleOnChange functions etc)
state = {
artists: [] // {}
}
handleOnClick = (e) => {
// put your logic here
this.setState({ whatever: e.target.value });
}
- Container renders two component (one for each column)
// import the components here
import ArtistItem from 'components/ArtistItem';
import ArtistDetails from 'components/ArtistDetails';
import ArtistRequests from 'components/ArtistRequests';
class SomeComponent extends React.Component {
state = {};
render() {
return (
<div className'container'>
<div className'col'>
<ArtistItem />
</div>
<div className='col'>
<ArtistDetails />
<ArtistRequest />
</div>
</div>
)
}
}
- Component's job will be to to render the view (what you see) with the help of the data
- You do this with using props
// ({ firstName, lastName }) is the same as (props)
// except now you don't have to use props.firstName, props.lastName
// read https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment for more info
// skip to object destructuring
const ArtistItem = ({ firstName, lastName }) => {
return (
<div className='container'>
<div>{firstName}</div>
<div>{lastName}</div>
</div>
);
}
- Pass the data (from state) to the component
- Pass the event handler functions to the component
class SomeComponent extends React.Component {
state = {
artists: [
{ id: 1, firstName: 'aaa', lastName: 'vbbb' },
{ id: 2, firstName: 'ccc', lastName: 'ddd' },
]
};
onArtistItemClick = (id) => {
// do something
}
render() {
return (
<div className'container'>
<div className'col'>
{this.state.artists.map(artist => {
return (
<ArtistItem
key={artist.id}
artist={artist}
onArtistItemClick={this.onArtistItemClick}
/>
)
})}
</div>
<div className='col'>
<ArtistDetails />
<ArtistRequest />
</div>
</div>
)
}
}
- Use a selectedArtist to track the id of the item selected state
state = {
artist: [],
selectedArtist: 1
};
handleArtistItemClick = (id) => {
// put your logic here
this.setState({ selectedArtist: id });
}
-
To pass the id from the component back to the container do the ff:
-
PS: you can attach an
Onclickhandler in divs, span and other elements too -
What's happening here is we are lifting the state back up to the parent component so it can store it in the state (Lifting state)
-
To make it easy to deal with the state, keep it as much as possible in your top level component (ArtistManagementPage.js, TagManagementPage.js)
const ArtistItem = ({ id, firstName, lastName, onArtistItemClick }) => {
return (
<div className='container' onClick={() => onArtistItemClick(id)}>
<div>{firstName}</div>
<div>{lastName}</div>
</div>
);
};
- Since we can now track with item is clicked, we can just pass the corresponding artist
- In the example I use to
findto get the selected artist based on id and pass that to<ArtistDetails /> - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
class SomeComponent extends React.Component {
state = {
artists: [
{ id: 1, firstName: 'aaa', lastName: 'vbbb' },
{ id: 2, firstName: 'ccc', lastName: 'ddd' },
],
selectedArtist: 1,
};
onArtistItemClick = (id) => {
// do something
}
render() {
return (
<div className'container'>
<div className'col'>
{this.state.artists.map(artist => {
return (
<ArtistItem
key={artist.id}
artist={artist}
onArtistItemClick={this.onArtistItemClick}
/>
)
})}
</div>
<div className='col'>
<ArtistDetails
artist={this.state.artists.find(artist => artist.id === this.state.selectedArtist)}
/>
<ArtistRequest />
</div>
</div>
)
}
}
# Pseudocode only
# Just look at line 219
# Just take note of how we're checking if `selectedArtist === artist.id` before rendering the details
# else just return null (which is the equivalent of not rendering anything)
return artist.map(artist => (
<ArtistItem
onClick={() => this.onSelectItem(artist.id)}
artist={artist}
/>
{this.state.selectedArtist === artist.id ? <ArtistDetails artist={} /> : null}
))
- Remember, you can use
&&as a guard https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Short-circuit_evaluation
state = {
showDiv: false,
showDiv2: '',
showDiv3: 0,
showDiv4: undefined,
showDiv5: 'this is a string'
}
render() {
// won't show anything
return this.state.showDiv && <div>showing</div>
// won't show anything
return this.state.showDiv2 && <div>showing</div>
// won't show anything
return this.state.showDiv3 && <div>showing</div>
// won't show anything
return this.state.showDiv4 && <div>showing</div>
// will return `<div>showing</div>
return this.state.showDiv5 && <div>showing</div>
}
- Important! Make sure to use
&&when mapping an array because using.maponundefinedwill cause an error
state = {
artists: null
}
// This will crash your program because `undefined` has no `map`
return artists.map(artist => <ArtistItem artist{artist} />)
// Do this instead
return artists && artists.map(artist => <ArtistItem artist={artist} />)
// Will not render anything (since `artist.map` will not even execute) if artist is `falsy`
// Else, will render the `ArtistItems`