ReactDOM.render(JSX or <component/>, elementToMountOn)
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
text: "Hello"
};
// Change code below this line
this.handleClick = this.handleClick.bind(this)
// Change code above this line
}
handleClick() {
this.setState({
text: "You clicked!"
});
}
render() {
return (
<div>
{ /* Change code below this line */ }
<button onClick={this.handleClick}>Click Me</button>
{ /* Change code above this line */ }
<h1>{this.state.text}</h1>
</div>
);
}
};
class MyApp extends React.Component {
constructor(props) {
super(props);
this.state = {
inputValue: ''
}
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({
inputValue: event.target.value
});
}
render() {
return (
<div>
{ /* Change code below this line */ }
<GetInput input={this.state.inputValue} handleChange={this.handleChange}/>
<RenderInput input={this.state.inputValue}/>
{ /* Change code above this line */ }
</div>
);
}
};
class GetInput extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h3>Get Input:</h3>
<input
value={this.props.input}
onChange={this.props.handleChange}/>
</div>
);
}
};
const DemoComponent = function(){
return (
<div className="customClass"/>
)
}
class Kitten extends React.Component{
constructor(props){
super(props);
}
render(){
return (
<h1>Hi!</h1>
)
}
}
const Fruits = () =>{
return (
<div>
Fruits
</div>
)
}
const Vegetables = () =>{
return (
<div>
Vegetables
</div>
)
}
class Foods extends React.Component{
constructor(props){
super(props)
}
render(){
return (
<div>
<Fruits/>
<Vegetables/>
</div>
)
}
}
Mounting:
Updating:
Unmount:
<div v-if="charged">You were charged</div>
const JSX = (
<div>
{/* some comment here */}
<h1 className="hello">Hello</h1>
</div>
)
//Render JSX
ReactDOM.render(JSX, document.getElementById('challenge-node'))
className
to define class in html
onClick
, instead of onclick
<div/>
= <div></div>
const List = () = {
return (
<p>{props.tasks.join(', ')}</p>
)
}
<List tasks={["learn react","learn state"]}>
ShoppingCart.defaultProps = {
items:0
}
ShoppingCart.propTypes = {
items: PropTypes.func.isRequired
}
// items should be of type function
// items is a required property
Redux Thunk middleware
create redux store
const reducer = (state = 5) => state
const store = Redux.createStore(reducer)
get current state from store
store.getState()
Define Action, change state -> done by dispatching action
const action = {
type: 'LOGIN',
}
Define action creator
const actionCreator = () => {
return action
}
Dispatch action to store
store.dispatch(action)
store.dispatch(actionCreator)
reducer
const authReducer = (state = defaultState, action) => {
switch (action.type) {
case 'LOGIN':
return {
authenticated: true,
}
default:
return state
}
}
subscribe - called when action are dispatched against store
store.subscribe(function () {
count += 1
})
composing reducers
const rootReducer = Redux.combineReducers({
auth: authReducer,
count: counterReducer,
})
const store = Redux.createStore(rootReducer)
handle async operation
const handleAsync = () => {
return function (dispatch) {
// Dispatch request action here
dispatch(requestingData())
setTimeout(function () {
let data = {
users: ['Jeff', 'William', 'Alice'],
}
// Dispatch received data action here
dispatch(receivedData(data))
}, 2500)
}
}
const store = Redux.createStore(
asyncDataReducer,
Redux.applyMiddleware(ReduxThunk.default)
)
useRef()
is basically useState(React.createRef())[0]
const [value, setValue] = useState(initialValue)
if initialValue is a computation, make it function, ie instead of this
const [] = useState(localStorage.getItem('name') || '')
do this
const [] = useState(() => localStorage.getItem('name') || '')
useEffect(() => {
setCount((oldValue) => (oldValue += 1))
})
data(){ return {
} }
encapsulated within component
useEffect(callback, dependencyArray)
custom hook: a function that uses hooks
to give hint to eslint system, custom hook should start with use
, just a convention to tell ecosystem that it is custom hook
function useLocalState(key, defaultValue) {
const [state, setState] = useState(() => {
return localStorage.getItem(key) || defaultValue
})
useEffect(() => {
localStorage.setItem(key, state)
}, [key, state])
return [state, setState]
}
as a good practice, always serialize/deserialize data before reading/writing to localStorage
const [state, setState] = useState(() => {
const value = localStorage.getItem(key)
if (value) {
return JSON.parse(value)
}
return defaultValue
})
useEffect(() => {
localStorage.setItem(key, JSON.stringify(state))
}, [key, state])
sometimes you want to separate the state logic from the components that make the state changes.
if you have multiple elements of state that typically change together, then having an object that contains those elements of state can be quite helpful.
as useState
const countReducer = (state, newState) => newState
function Counter({ initialCount = 0, step = 1 }) {
const [count, setCount] = React.useReducer(countReducer, initialCount)
const increment = () => setCount(count + step)
return <button onClick={increment}>{count}</button>
}
const countReducer = (count, change) => count + change
function Counter({ initialCount = 0, step = 1 }) {
const [count, changeCount] = React.useReducer(countReducer, initialCount)
const increment = () => changeCount(step)
return <button onClick={increment}>{count}</button>
}
const countReducer = (state, action) => ({
...state,
...(typeof action === 'function' ? action(state) : action),
})
function Counter({ initialCount = 0, step = 1 }) {
const [state, setState] = React.useReducer(countReducer, {
count: initialCount,
})
const { count } = state
const increment = () =>
setState((currentState) => ({ count: currentState.count + step }))
return <button onClick={increment}>{count}</button>
}
function countReducer(state, action) {
const { type, step } = action
switch (type) {
case 'increment': {
return {
...state,
count: state.count + step,
}
}
default: {
throw new Error(`Unsupported action type: ${type}`)
}
}
}
function Counter({ initialCount = 0, step = 1 }) {
const [state, dispatch] = React.useReducer(countReducer, {
count: initialCount,
})
const { count } = state
const increment = () => dispatch({ type: 'increment', step })
return <button onClick={increment}>{count}</button>
}