Skip to content

New sample state callback #124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions 03 State/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
},
"dependencies": {
"bootstrap": "^4.1.0",
"npm": "^6.0.0",
"react": "^16.3.1",
"react-dom": "^16.3.1"
}
Expand Down
10 changes: 10 additions & 0 deletions _misc/00 state-callback/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"presets": [
[
"env",
{
"modules": false
}
]
]
}
37 changes: 37 additions & 0 deletions _misc/00 state-callback/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "sample",
"version": "1.0.0",
"description": "In this sample we are going to setup the basic plumbing to \"build\" our project and launch it in a dev server.",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server --mode development --inline --hot --open",
"build": "webpack --mode development",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@types/node": "^6.0.106",
"@types/react": "^16.3.8",
"@types/react-dom": "^16.0.5",
"awesome-typescript-loader": "^5.0.0",
"babel-core": "^6.26.0",
"babel-preset-env": "^1.6.1",
"css-loader": "^0.28.11",
"file-loader": "^1.1.11",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.4.0",
"style-loader": "^0.20.3",
"typescript": "^2.8.1",
"url-loader": "^1.0.1",
"webpack": "^4.5.0",
"webpack-cli": "^2.0.14",
"webpack-dev-server": "3.1.0"
},
"dependencies": {
"bootstrap": "^4.1.0",
"npm": "^6.0.0",
"react": "^16.3.1",
"react-dom": "^16.3.1"
}
}
145 changes: 145 additions & 0 deletions _misc/00 state-callback/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# 00 State Call back

In this sample we are agoing to see the async nature of setState mehtod.

In this method we could use a callback to ensure we have the change applied.

We will take as a starting point sample _04 Callback_:

## Summary steps:

- Change nameEdit.tsx to add a boolean property to Props and add a checkbox input
- Change app.tsx to add a boolean property to State and a call back to update the input in the control
- Check everything is working properly.

## Prerequisites

Install [Node.js and npm](https://nodejs.org) if they are not already installed on your computer.

> Verify that you are running at least node v6.x.x and npm 3.x.x by running `node -v` and `npm -v` in a terminal/console window. Older versions may produce errors.

## Steps to build it

- Copy the content from _04 Callback and execute `npm install`.

- Let's change _nameEdit.tsx_ to modify the Props and render method to add a new control to show the value was changed.

_./src/nameEdit.tsx_

```diff
interface Props {
initialUserName : string;
onNameUpdated : (newName: string) => void;
+ changed: boolean;
}

...

public render(){
return(
<>
<label>Update Name:</label>
<input value={this.state.editingName} onChange={this.onChange} />
<button className="btn btn-default" onClick={this.onNameSubmit}>Change</button>
+ <div>
+ <span>Changed: </span>
+ <input type="checkbox" checked={this.props.changed} title="Is it changed?"/>
+ </div>
"/>
</>
);
```

- Let's update _app.tsx_ just to change the _constructor_, the _setUsernameState_ method, and add a new method to manage when the change is applied.

_./src/app.tsx_

```diff

interface State {
userName: string;
+ changed: boolean;
}

...

constructor(props: Props) {
super(props);
- this.state = { userName: 'defaultUserName' };
+ this.state = { userName: 'defaultUserName', changed: false };
}

setUsernameState = (newName: string) => {
- this.setState({userName: newName});
+ this.setState({userName: newName}, this.nameChanged);
}

+ nameChanged() {
+ this.setState({changed:true});
+ }

public render() {
return (
<>
<HelloComponent userName={this.state.userName} />
- <NameEditComponent initialUserName={this.state.userName} onNameUpdated= this.setUsernameState}/>
+ <NameEditComponent initialUserName={this.state.userName}
+ onNameUpdated={this.setUsernameState}
+ changed={this.state.changed} />
</>
);
}
```

- Now we can check that things are still working as expected (nothing broken so far).

```
npm start
```




- In the _app.tsx_ file let's add a function to set the changed _userName_ in the state.

```diff
import * as React from 'react';
import {HelloComponent} from './hello';
+ import {NameEditComponent} from './nameEdit';

interface Props {
}

interface State {
userName : string;
}

export class App extends React.Component<Props, State> {
constructor(props : Props) {
super(props);

this.state = {userName: 'defaultUserName'};
}

+ setUsernameState = (event) => {
+ this.setState({userName: event.target.value});
+ }

public render() {
return (
+ <>
<HelloComponent userName={this.state.userName} />
+ <NameEditComponent userName={this.state.userName} onChange={this.setUsernameState} />
+ </>
);
}
}
```

> Note down the fat arrow class method, this will avoid loosing the _this_ context on the callback

- Finally let's test the final sample.

```
npm start
```
39 changes: 39 additions & 0 deletions _misc/00 state-callback/src/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import * as React from 'react';
import { HelloComponent } from './hello';
import { NameEditComponent } from './nameEdit';

interface Props {
}

interface State {
userName: string;
changed: boolean;
}

export class App extends React.Component<Props, State> {

constructor(props: Props) {
super(props);

this.state = { userName: 'defaultUserName', changed: false };
}

setUsernameState = (newName: string) => {
this.setState({userName: newName}, this.nameChanged);
}

nameChanged() {
this.setState({changed:true});
}

public render() {
return (
<>
<HelloComponent userName={this.state.userName} />
<NameEditComponent initialUserName={this.state.userName}
onNameUpdated={this.setUsernameState}
changed={this.state.changed} />
</>
);
}
}
7 changes: 7 additions & 0 deletions _misc/00 state-callback/src/hello.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as React from 'react';

export const HelloComponent = (props: {userName : string}) => {
return (
<h2>Hello user: {props.userName} !</h2>
);
}
13 changes: 13 additions & 0 deletions _misc/00 state-callback/src/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div class="well">
<h1>Sample app</h1>
<div id="root"></div>
</div>
</body>
</html>
8 changes: 8 additions & 0 deletions _misc/00 state-callback/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { App } from './app';

ReactDOM.render(
<App/>,
document.getElementById('root')
);
41 changes: 41 additions & 0 deletions _misc/00 state-callback/src/nameEdit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import * as React from 'react';

interface Props {
initialUserName : string;
onNameUpdated : (newName: string) => void;
changed: boolean;
}

interface State{
editingName: string;
}

export class NameEditComponent extends React.Component<Props, State>{
constructor(props: Props){
super(props);
this.state = {editingName: this.props.initialUserName};
}

onChange = (event) =>{
this.setState({editingName: event.target.value});
}

onNameSubmit = (event: any): any => {
this.props.onNameUpdated(this.state.editingName);
}

public render(){
return(
<>
<label>Update Name:</label>
<input value={this.state.editingName} onChange={this.onChange} />
<button className="btn btn-default" onClick={this.onNameSubmit}>Change</button>
<div>
<span>Changed: </span>
<input type="checkbox" checked={this.props.changed} title="Is it changed?"/>
</div>
</>
);
}
}

17 changes: 17 additions & 0 deletions _misc/00 state-callback/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "es6",
"module": "es6",
"moduleResolution": "node",
"declaration": false,
"noImplicitAny": false,
"jsx": "react",
"sourceMap": true,
"noLib": false,
"suppressImplicitAnyIndexErrors": true
},
"compileOnSave": false,
"exclude": [
"node_modules"
]
}
Loading