TypeScript
-
New project
yarn create react-app my-app --template typescript
-
Existing project
-
npm i -S typescript @types/node @types/react @types/react-dom @types/jest
-
Rename JS source code file to be a
TypeScript
file (e.g.src/index.js
tosrc/index.tsx
) and restart your development server!
-
-
Resources
API
setState
-
Asynchronous invocation
-
Use callback to update state to ensure access to the latest state
this.setState((state, props) => { if (state.currentQuestionIndex !== null && state.currentQuestionIndex > 0) { return Object.assign({}, state, { currentQuestionIndex: state.currentQuestionIndex - 1, }); } });
-
Simplified updater function signature:
(prevState, prevProps) => <object with keys defined in state>
this.setState((state) => { return { checked: !state.checked }; }); // Alternatively, simplified as below, note the parenthesis around the returned object is mandatory this.setState((state) => ({ checked: !state.checked }));
PureComponent
-
PureComponent
only checkes reassignment of state variables. In the case of an array, mutation of the array content cannot be detected.-
The simplest way to avoid this problem is to avoid mutating values that you are using as props or state.
// state variable is an array this.setState(state => ({ words: state.words.concat(["marklar"]); // Or words: [...state.words, 'marklar'] })); // state variable is an object this.setState(state => ({ colormap: Object.assign({}, state, { right: "blue" }); }));
-
When using TypeScript, use
readonly
to ensure object immutability. Create a new object with updated values and replace the old object to achieve modification.
-
JSX
Optional attributes of components
Using spread opeartor
to add optional attributes:
public render() {
const {menuPlacement, menuPosition} = this.props;
const opts: Partial<Props<IOption>> = {};
if (this.props.parentRef != null) {
opts.menuPortalTarget = this.props.parentRef.current;
}
return (
<Select options={LabelAutocomplete.generateOptions(this.props.labels)}
backspaceRemovesValue={false}
closeMenuOnSelect={false}
value={this.state.value}
onChange={this.onChange}
inputValue={this.state.inputValue}
isSearchable={true}
onInputChange={this.onInputChange}
placeholder="Select labels"
minMenuHeight={100}
maxMenuHeight={150}
menuIsOpen={this.state.isMenuOpen}
menuPlacement={menuPlacement}
menuPortalTarget={document.body}
menuPosition={menuPosition}
onMenuOpen={this.onMenuOpen}
onMenuClose={this.onMenuClose}
styles={selectStyles}
isMulti={true}
{...opts} />
);
}
Default properties of components
Support for defaultProps in JSX (opens in a new tab)
Pass value from child to parent component
- Define an
arrow function
in parent to change state - Pass the function reference to child as a
prop
- Invoke the function in child via an event handler and pass the value as argument
// Parent
class ParentComponent extends React.Component {
state: { language: "" };
handleLanguage = (langValue) => {
this.setState({ language: langValue });
};
render() {
return (
<div className="col-sm-9">
<SelectLanguage onSelectLanguage={this.handleLanguage} />
</div>
);
}
}
// Child
var json = require("json!../languages.json");
var jsonArray = json.languages;
export class SelectLanguage extends React.Component {
state = {
selectedCode: "",
selectedLanguage: jsonArray[0],
};
handleLangChange = () => {
var lang = this.dropdown.value;
this.props.onSelectLanguage(lang);
};
render() {
return (
<div>
<DropdownList
ref={(ref) => (this.dropdown = ref)}
data={jsonArray}
valueField="lang"
textField="lang"
caseSensitive={false}
minLength={3}
filter="contains"
onChange={this.handleLangChange}
/>
</div>
);
}
}
Use && for concise conditional rendering
render() {
// change code below this line
return (
<div>
<button onClick={this.toggleDisplay}>Toggle Display</button>
{this.state.display && <h1>Displayed!</h1>}
</div>
);
}
Redux
- Application state should be stored in a single immutable object.
Code Organization with ES6 Modules
src/
index.js
index.css
constants/
index.js
components/
App/
index.js
test.js
index.css
Button/
index.js
test.js
index.css
- When you use the
index.js
naming convention, you can omit the filename from the relative path. - The
index.js
file is the entry point to a module. It describes the public API to the module. External modules are only allowed to use theindex.js
file to import shared code from the module.