0% found this document useful (0 votes)
36 views23 pages

Redux State Management Basics

The document provides a comprehensive introduction to Redux, explaining its principles, including a single source of truth and the use of actions, reducers, and stores to manage application state. It includes practical examples of implementing Redux with plain JavaScript, covering action creators, reducers, and handling complex state. Additionally, it discusses combining reducers and showcases challenges to reinforce learning through practical coding tasks.

Uploaded by

sainath
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
36 views23 pages

Redux State Management Basics

The document provides a comprehensive introduction to Redux, explaining its principles, including a single source of truth and the use of actions, reducers, and stores to manage application state. It includes practical examples of implementing Redux with plain JavaScript, covering action creators, reducers, and handling complex state. Additionally, it discusses combining reducers and showcases challenges to reinforce learning through practical coding tasks.

Uploaded by

sainath
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

1)Redux Introduction:

===================

What about React State ?

"I thought React already had state, why do i need a separate" tool to do it ?" -you

--> How to handle state that your whole application needs.


--> Lack of organization and clarity.

Guidelines principals

--> A single source of truth("global state")


--> State is read-only("actions")
--> Changes are made with pure functions("reducers")

Fundamentals:
==============
1) Actions & action creators
2) Dispatch
3) Reducers
4) Store

2)Plain JS Redux - Overview:


============================
[email protected] package

[Link]:
=========

const redux = require("redux")


const initialState = {
count: 0
}

function reducer(state=initialState, action) {


switch([Link]) {
case "INCREMENT":
return {
count: [Link] + 1
}
case "DECREMENT":
return {
count: [Link] - 1
}
default:
return state
}
}

const store = [Link](reducer)

[Link](() => {
[Link]([Link]())
})

[Link]({type: "INCREMENT"})
[Link]({type: "INCREMENT"})
[Link]({type: "DECREMENT"})

3)Plain JS Redux - Actions:


===========================

[Link]:
=========
const redux = require("redux")

const action = {
type: "INCREMENT"
}

4)Plain JS Redux - Action Creators:


===================================
const redux = require("redux")

function increment() {
return {
type: "INCREMENT"
}
}

[Link](increment())

5)Plain JS Redux - Reducer:


===========================

[Link]:
=========
const redux = require("redux")

function increment() {
return {
type: "INCREMENT"
}
}

function decrement() {
return {
type: "DECREMENT"
}
}

function reducer(state = {count: 0}, action) {


// return new state based on the incoming [Link]
switch([Link]) {
case "INCREMENT":
return {
count: [Link] + 1
}
case "DECREMENT":
return {
count: [Link] - 1
}
default:
return state
}
}

6)Plain JS Redux Practice 1:


============================

/**
* Challenge:
*
* Enable the ability to double and halve the count.
* If halving, round down instead of letting your count
* become a decimal.
*/

[Link]:
=========
/**
* Challenge:
*
* Do it again, from scratch!
*
* 1. Action creators for increment, decrement, double, and halve
* 2. Reducer to handle these actions 👆🏻
*/

function increment() {
return {
type: "INCREMENT"
}
}

function decrement() {
return {
type: "DECREMENT"
}
}

function double() {
return {
type: "DOUBLE"
}
}

function halve() {
return {
type: "HALVE"
}
}

function reducer(state = 0, action) {


switch([Link]) {
case "INCREMENT":
return state + 1
case "DECREMENT":
return state - 1
case "DOUBLE":
return state * 2
case "HALVE":
return [Link](state / 2)
default:
return state
}
}

7)Plain JS Redux - Creating the Store:


======================================
we need to get store object by using redux methoud createStore(reducer function)

const store = [Link](reducer)


[Link](store)

[Link]:
=========

const redux = require("redux")

function increment() {
return {
type: "INCREMENT"
}
}

function decrement() {
return {
type: "DECREMENT"
}
}

function reducer(state = {count: 0}, action) {


// return new state based on the incoming [Link]
switch([Link]) {
case "INCREMENT":
return {
count: [Link] + 1
}
case "DECREMENT":
return {
count: [Link] - 1
}
default:
return state
}
}

const store = [Link](reducer)


[Link](store)

8)Plain JS Redux - subscribe and getState:


==========================================
by using store object we can subscribe and getState of an object

const store = [Link](reducer)

[Link](()=>{
getState()
})
[Link]:
=========
const redux = require("redux")

function increment() {
return {
type: "INCREMENT"
}
}

function decrement() {
return {
type: "DECREMENT"
}
}

function reducer(state = {count: 0}, action) {


// return new state based on the incoming [Link]
switch([Link]) {
case "INCREMENT":
return {
count: [Link] + 1
}
case "DECREMENT":
return {
count: [Link] - 1
}
default:
return state
}
}

const store = [Link](reducer)


[Link](() => {
[Link]([Link]())
})

9)Plain JS Redux - dispatch


===========================
[Link](actiontype as parameter to pass the values to reducer)

[Link]:
========
const redux = require("redux")

function increment() {
return {
type: "INCREMENT"
}
}

function decrement() {
return {
type: "DECREMENT"
}
}
function reducer(state = {count: 0}, action) {
// return new state based on the incoming [Link]
switch([Link]) {
case "INCREMENT":
return {
count: [Link] + 1
}
case "DECREMENT":
return {
count: [Link] - 1
}
default:
return state
}
}

const store = [Link](reducer)


[Link](() => {
[Link]([Link]())
})

[Link](increment())
[Link]({type:"INCREMENT"})

10)Plain JS Redux - Payload in action creators:


===============================================
Dynamic passing action types into reducer

[Link]:
=========
const redux = require("redux")

function changeCount(amount = 1) {
return {
type: "CHANGE_COUNT",
payload: amount
}
}

function reducer(state = {count: 0}, action) {


switch([Link]) {
case "CHANGE_COUNT":
return {
count: [Link] + [Link]
}
default:
return state
}
}

const store = [Link](reducer)


[Link](() => {
[Link]([Link]())
})

[Link](changeCount())

11)Plain JS Redux - Handling more complex state:


================================================
[Link]:
=========
const redux = require("redux")

function changeCount(amount = 1) {
return {
type: "CHANGE_COUNT",
payload: amount
}
}

function addFavoriteThing(thing) {
return {
type: "ADD_FAVORITE_THING",
payload: thing
}
}

const initialState = {
count: 0,
favoriteThings: []
}

function reducer(state = initialState, action) {


switch([Link]) {
case "CHANGE_COUNT":
return {
...state,
count: [Link] + [Link]
}
case "ADD_FAVORITE_THING":
return {
...state,
favoriteThings: [...[Link], [Link]]
}
default:
return state
}
}

const store = [Link](reducer)


[Link](() => {
[Link]([Link]())
})

[Link](changeCount(2))
[Link](addFavoriteThing("Raindrops on roses"))
[Link](addFavoriteThing("Whiskers on kittens"))

14)Plain JS Redux - Practice::


==============================
/**
* Challenge: implement an action creator called `removeFavoriteThing` which takes
the string
* of the favorite thing you want to remove from the array and removes it
*/

[Link]:
=========

const redux = require("redux")

function changeCount(amount = 1) {
return {
type: "CHANGE_COUNT",
payload: amount
}
}

function addFavoriteThing(thing) {
return {
type: "ADD_FAVORITE_THING",
payload: thing
}
}

function removeFavoriteThing(thing) {
return {
type: "REMOVE_FAVORITE_THING",
payload: thing
}
}

const initialState = {
count: 0,
favoriteThings: []
}

function reducer(state = initialState, action) {


switch([Link]) {
case "CHANGE_COUNT":
return {
...state,
count: [Link] + [Link]
}
case "ADD_FAVORITE_THING":
return {
...state,
favoriteThings: [...[Link], [Link]]
}
case "REMOVE_FAVORITE_THING": {
const arrCopy = [...[Link]]

const updatedArr = [Link](thing =>


[Link]() !== [Link]())
return {
...state,
favoriteThings: updatedArr
}
}
default:
return state
}
}

const store = [Link](reducer)


[Link](() => {
[Link]([Link]())
})

[Link](addFavoriteThing("Raindrops on roses"))
[Link](addFavoriteThing("Whiskers on kittens"))

/**
* Challenge: implement an action creator called `removeFavoriteThing` which takes
the string
* of the favorite thing you want to remove from the array and removes it
*/
[Link](removeFavoriteThing("raindrops on roses"))

15)Plain JS Redux - Even more complex state:


============================================

[Link]:
=========
const redux = require("redux")

function changeCount(amount = 1) {
return {
type: "CHANGE_COUNT",
payload: amount
}
}

function addFavoriteThing(thing) {
return {
type: "ADD_FAVORITE_THING",
payload: thing
}
}

function removeFavoriteThing(thing) {
return {
type: "REMOVE_FAVORITE_THING",
payload: thing
}
}

function setYouTubeTitle(title) {
return {
type: "SET_YOUTUBE_TITLE",
payload: title
}
}

function upvoteVideo() {
return {
type: "UPVOTE_VIDEO"
}
}

const initialState = {
count: 0,
favoriteThings: [],
youtubeVideo: {
title: "",
viewCount: 0,
votes: {
up: 0,
down: 0
}
}
}
[Link](initialState)

/**
* Challenge:
* Implement an action creator and reducer case to handle upvoting our YouTube
video (+1)
*/

function reducer(state = initialState, action) {


switch([Link]) {
case "CHANGE_COUNT":
return {
...state,
count: [Link] + [Link]
}
case "ADD_FAVORITE_THING":
return {
...state,
favoriteThings: [...[Link], [Link]]
}
case "REMOVE_FAVORITE_THING": {
const arrCopy = [...[Link]]

const updatedArr = [Link](thing =>


[Link]() !== [Link]())
return {
...state,
favoriteThings: updatedArr
}
}
case "SET_YOUTUBE_TITLE":
return {
...state,
youtubeVideo: {
...[Link],
title: [Link]
}
}
case "UPVOTE_VIDEO":
return {
...state,
youtubeVideo: {
...[Link],
votes: {
...[Link],
up: [Link] + 1
}
}
}
default:
return state
}
}

const store = [Link](reducer)


[Link](() => {
[Link]([Link]())
})

[Link](setYouTubeTitle("Learn Redux"))
[Link](upvoteVideo())

16 17)Plain JS Redux - combineReducers Part 1 $ Part 2:


=======================================================
// import the separate reducers
// combine the reducers into a single state tree
// create the store
// export the store

redux/[Link]:
===============
export function changeCount(amount = 1) {
return {
type: "CHANGE_COUNT",
payload: amount
}
}

export default function countReducer(count = 0, action) {


switch([Link]) {
case "CHANGE_COUNT":
return count + [Link]
default:
return count
}
}

redux/[Link]:
=========================
export function addFavoriteThing(thing) {
return {
type: "ADD_FAVORITE_THING",
payload: thing
}
}

export function removeFavoriteThing(thing) {


return {
type: "REMOVE_FAVORITE_THING",
payload: thing
}
}

export default function favoriteThingsReducer(favoriteThings = [], action) {


switch([Link]) {
case "ADD_FAVORITE_THING":
return [...favoriteThings, [Link]]
case "REMOVE_FAVORITE_THING": {
const updatedArr = [Link](thing => [Link]() !
== [Link]())
return updatedArr
}
default:
return favoriteThings
}
}

redux/[Link]:
======================
export function setYouTubeTitle(title) {
return {
type: "SET_YOUTUBE_TITLE",
payload: title
}
}

export function incrementViewCount() {


return {
type: "INCREMENT_VIEW_COUNT"
}
}

export function upvoteVideo() {


return {
type: "UPVOTE_VIDEO"
}
}

export function downvoteVideo() {


return {
type: "DOWNVOTE_VIDEO"
}
}

const initialState = {
title: "",
viewCount: 0,
votes: {
up: 0,
down: 0
}
}

export default function youTubeVideoReducer(youTubeVideo = initialState, action) {


switch([Link]) {
case "INCREMENT_VIEW_COUNT":
return {
...youTubeVideo,
viewCount: [Link] + 1
}
case "SET_YOUTUBE_TITLE":
return {
...youTubeVideo,
title: [Link]
}
case "UPVOTE_VIDEO":
return {
...youTubeVideo,
votes: {
...[Link],
up: [Link] + 1
}
}
case "DOWNVOTE_VIDEO":
return {
...youTubeVideo,
votes: {
...[Link],
down: [Link] + 1
}
}
default:
return youTubeVideo
}
}

redux/[Link]:
=========
// import the separate reducers
// combine the reducers into a single state tree
// create the store
// export the store

const redux = require("redux")


const {combineReducers, createStore} = redux
import countReducer from "./count"
import favoriteThingsReducer from "./favoriteThings"
import youTubeVideoReducer from "./youTubeVideo"

const rootReducer = combineReducers({


count: countReducer,
favoriteThings: favoriteThingsReducer,
youTubeVideo: youTubeVideoReducer
})

const store = createStore(rootReducer)


[Link](() => {
[Link]([Link]())
})
export default store

[Link]:
=========
import store from "./redux"
import {changeCount} from "./redux/count"

[Link](changeCount(42))

18)Plain JS Redux Practice 1:


==============================
/**
* Challenge:
*
* 1. Bring in all the action creators we've made so far and dispatch them, just to
make sure things are working
*/

above combine part 1 and part 2 same


===================================

[Link]:
=========
import store from "./redux"
import {changeCount} from "./redux/count"
import {addFavoriteThing, removeFavoriteThing} from "./redux/favoriteThings"
import {setYouTubeTitle, incrementViewCount, upvoteVideo, downvoteVideo} from
"./redux/youTubeVideo"

/**
* Challenge:
*
* 1. Bring in all the action creators we've made so far and dispatch them, just to
make sure things are working
*/

[Link](changeCount(42))
[Link](addFavoriteThing("Door bells"))
[Link](addFavoriteThing("Sleigh bells"))
[Link](removeFavoriteThing("door bells"))
[Link](setYouTubeTitle("Learning Redux is Fun!"))
[Link](incrementViewCount())
[Link](upvoteVideo())
[Link](incrementViewCount())
[Link](upvoteVideo())
[Link](incrementViewCount())
[Link](upvoteVideo())
[Link](downvoteVideo())

/*

{count: 42, favoriteThings: [], youTubeVideo: {title: "", viewCount: 0, votes: {up:
0, down: 0}}}

{count: 42, favoriteThings: ["Door bells"], youTubeVideo: {title: "", viewCount: 0,


votes: {up: 0, down: 0}}}

{count: 42, favoriteThings: ["Door bells", "Sleigh bells"], youTubeVideo: {title:


"", viewCount: 0, votes: {up: 0, down: 0}}}

{count: 42, favoriteThings: ["Sleigh bells"], youTubeVideo: {title: "", viewCount:


0, votes: {up: 0, down: 0}}}

{count: 42, favoriteThings: ["Sleigh bells"], youTubeVideo: {title: "Learning Redux


is Fun!", viewCount: 0, votes: {up: 0, down: 0}}}

{count: 42, favoriteThings: ["Sleigh bells"], youTubeVideo: {title: "Learning Redux


is Fun!", viewCount: 1, votes: {up: 0, down: 0}}}

{count: 42, favoriteThings: ["Sleigh bells"], youTubeVideo: {title: "Learning Redux


is Fun!", viewCount: 1, votes: {up: 1, down: 0}}}

{count: 42, favoriteThings: ["Sleigh bells"], youTubeVideo: {title: "Learning Redux


is Fun!", viewCount: 2, votes: {up: 1, down: 0}}}
{count: 42, favoriteThings: ["Sleigh bells"], youTubeVideo: {title: "Learning Redux
is Fun!", viewCount: 2, votes: {up: 2, down: 0}}}

{count: 42, favoriteThings: ["Sleigh bells"], youTubeVideo: {title: "Learning Redux


is Fun!", viewCount: 3, votes: {up: 2, down: 0}}}

{count: 42, favoriteThings: ["Sleigh bells"], youTubeVideo: {title: "Learning Redux


is Fun!", viewCount: 3, votes: {up: 3, down: 0}}}

{count: 42, favoriteThings: ["Sleigh bells"], youTubeVideo: {title: "Learning Redux


is Fun!", viewCount: 3, votes: {up: 3, down: 1}}}

*/

19)Plain JS Redux Practice 2:


==============================
same as above 18

[Link]:
=========

/**
* Challenge:
*
* Create a new state property to hold the currently-logged-in user info. I.e. if
our app wanted to allow a user to log in, we would likely want to keep track of
some info from the logged in user. For this challenge, you'll save a user with
these properties:
* {
* firstName: ___,
* lastName: ___,
* id: ___,
* email: ___
* }
*
* This will require
* (1) Creating a new file to hold our new Redux stuff re: the user (e.g.
[Link]),
* (2) Creating a new action creator (e.g. "setUserDetails"),
* (3) Creating a new reducer, and
* (4) Adding that reducer to our rootReducer with combineReducers
*/

redux/[Link]:
==============
export function setUserDetails(user) {
return {
type: "SET_USER_DETAILS",
payload: user
}
}

export function removeUserDetails() {


return {
type: "REMOVE_USER_DETAILS"
}
}
export default function userReducer(user = {}, action) {
switch([Link]) {
case "SET_USER_DETAILS":
return {
...user,
...[Link]
}
case "REMOVE_USER_DETAILS":
return {}
default:
return user
}
}
redux/[Link]:
===============

const redux = require("redux")


const {combineReducers, createStore} = redux
import countReducer from "./count"
import favoriteThingsReducer from "./favoriteThings"
import youTubeVideoReducer from "./youTubeVideo"
import userReducer from "./user"

const rootReducer = combineReducers({


count: countReducer,
favoriteThings: favoriteThingsReducer,
youTubeVideo: youTubeVideoReducer,
user: userReducer
})

const store = createStore(rootReducer)


[Link](() => {
[Link]([Link]())
})
export default store

main [Link]:
==============
import store from "./redux"
import {changeCount} from "./redux/count"
import {addFavoriteThing, removeFavoriteThing} from "./redux/favoriteThings"
import {setYouTubeTitle, incrementViewCount, upvoteVideo, downvoteVideo} from
"./redux/youTubeVideo"
import {setUserDetails, removeUserDetails} from "./redux/user"

[Link](setUserDetails({
firstName: "Joe",
lastName: "Schmoe",
id: 1,
email: "joe@[Link]"
}))
[Link](setUserDetails({
email: "[Link]@[Link]"
}))
[Link](removeUserDetails())

Important:
==========
18) Redux in React - Setup & Practice:
======================================
[email protected]
[email protected]

redux/[Link]:
===============
/**
* Challenge: set up redux action creators, reducer, and store
* We'll be building a counter app to start out.
* Read the comments below for the step-by-step challenges
*/

import redux, {createStore} from "redux"

function increment() {
return {
type: "INCREMENT"
}
}

function decrement() {
return {
type: "DECREMENT"
}
}

function reducer(count = 0, action) {


switch([Link]) {
case "INCREMENT":
return count + 1
case "DECREMENT":
return count - 1
default:
return count
}
}

const store = createStore(reducer)


[Link](() => [Link]([Link]()))
export default store

// 1. Create action creators for having the count "increment" and "decrement"

// 2. Create a reducer to handle your increment and decrement actions

// 3. Create a new Redux store

// 4. Set up the subscribe function so we can more easily see the changes to the
Redux state as they happen

// 5. Export the store as a default export


19)Redux in React - react-redux & Provider:
===========================================
same example above 18 Redux in React - react-redux & Provider

[Link]:
=========
import React from "react"
import ReactDOM from "react-dom"
import {Provider} from "react-redux"
import store from "./redux"

import App from "./App"

[Link](
<Provider store={store}>
<App />
</Provider>,
[Link]("root")
)

20)Redux in React - connect()


=============================
--> How does connect work?
--> Pass 2 things:
1."What parts of the global state does this component want access to ?"
2."What actions do you want to be able to dispatch from this component ?"
--> It then returns a function to which you pass the component you want to connect.
When called, this function creates a new component wrapping yours which passes
the
global state and "dispatchable" actions to your component via props.

--> connect("What parts of state do you want ? ","What actions do you want to
dispatch ?")(Components)
connect(mapStateToPropsFunc,mapDispatchToPropsFunc)(Component)

[Link]:
=======

import React from "react"


import {connect} from "react-redux"

function App(props) {
return (
<div>
<h1>COUNT GOES HERE</h1>
<button>-</button>
<button>+</button>
</div>
)
}

export default connect


(/* What parts of state do you want? */, /* What actions to dispatch? */)(App)
21)Redux in React - mapStateToProps:
==================================
function mapStateToProps(globalState) {
// return an object where the keys are the name of the prop your component
wants,
// values are the actual parts of the global state your component wants
return {
bananas: globalState
}
}

// Write the mapStateToProps function from scratch


// Takes the global state from Redux as a parameter
// returns an object where the keys are the name of the prop your component wants,
// and the values are the actual parts of the global state your component wants

[Link]:
=======
import React from "react"
import {connect} from "react-redux"

function App(props) {
return (
<div>
<h1>{[Link]}</h1>
<button>-</button>
<button>+</button>
</div>
)
}

// Write the mapStateToProps function from scratch


// Takes the global state from Redux as a parameter
// returns an object where the keys are the name of the prop your component wants,
// and the values are the actual parts of the global state your component wants
function mapStateToProps(state) {
return {
count: state
}
}

export default connect(mapStateToProps, {})(App)

22)Redux in React - mapDispatchToProps:


=======================================
redux/[Link]:
==============
import redux, {createStore} from "redux"

export function increment() {


return {
type: "INCREMENT"
}
}

export function decrement() {


return {
type: "DECREMENT"
}
}

function reducer(count = 0, action) {


switch([Link]) {
case "INCREMENT":
return count + 1
case "DECREMENT":
return count - 1
default:
return count
}
}

const store = createStore(reducer)


[Link](() => [Link]([Link]()))
export default store

[Link]:
=======
import React from "react"
import {connect} from "react-redux"
import {increment, decrement} from "./redux"

function App(props) {
return (
<div>
<h1>{[Link]}</h1>
<button onClick={[Link]}>-</button>
<button onClick={[Link]}>+</button>
</div>
)
}

// [Link]

export default connect(state => ({count: state}), {increment, decrement})(App)

22)Redux in React - useSelector():


==================================
[Link] replace useConnect with useSelector()
======

import React from "react"


import {useSelector} from "react-redux"
import {increment, decrement} from "./redux"

function App(props) {
const count = useSelector(state => state)
return (

)
}

// export default connect(state => ({count: state}), {increment, decrement})(App)


export default App
24)Redux in React - useDispatch():
==================================
replace connect(1,2) first parameter with useSelector and second parameter with
useDispatch():
-----------------------------------------------------------------------------------
-----------

[Link]:
=======
import React from "react"
import {useSelector, useDispatch} from "react-redux"
import {increment, decrement} from "./redux"

function App(props) {
const count = useSelector(state => state)
const dispatch = useDispatch()
return (
<div>
<h1>{count}</h1>
<button onClick={() => dispatch(decrement())}>-</button>
<button onClick={() => dispatch(increment())}>+</button>
</div>
)
}

export default App

// [Link]
// [Link]

25)Redux in React - Redux Thunk:


================================
not understood:
===============
[Link]:
=======
import redux, {createStore, applyMiddleware} from "redux"
import thunk from "redux-thunk"

export function increment() {


return (dispatch, getState) => {
const number = getState()
const baseUrl = "[Link]
fetch(`${baseUrl}/${number}`)
.then(res => [Link]())
.then(res => {
[Link](res)
dispatch({
type: "INCREMENT",
payload: res
})
})
}
}

/**
{name: "C-3PO", height: "167", mass: "75", hair_color: "n/a", skin_color: "gold",
eye_color: "yellow", birth_year: "112BBY", gender: "n/a", homeworld:
"[Link] films: ["[Link]
"[Link] "[Link]
"[Link] "[Link]
"[Link] species: ["[Link]
vehicles: [], starships: [], created: "2014-12-10T[Link].357000Z", edited: "2014-
12-20T[Link].309000Z", url: "[Link]

*/

export function decrement() {


return {
type: "DECREMENT"
}
}

function reducer(count = 0, action) {


switch([Link]) {
case "INCREMENT":
return count + 1
case "DECREMENT":
return count - 1
default:
return count
}
}

const store = createStore(reducer, applyMiddleware(thunk))


[Link](() => [Link]([Link]()))
export default store

Getting Hired - Edabit:


=======================

For Practicing Coding Challenges


[Link]

Codesignal:
===========
[Link]

pramp:
======
practice:

[Link]

Getting Hired - Problem Solving:


================================
George Polya --> how to solve it ?

1) Understand the problem

2) Devise a plan
3) Execute the plan

4) Review your solution

You might also like