Browse Source

Minor FAQ updates (#308)

* Don't use experimental syntax unless necessary

* Edit another page

* Update another page

* Unrelated bikeshed on virtual DOM

* Please, no *.jsx, we don't recommend it

* Update faq-structure.md

* Minor updates

* Update faq-ajax.md

* Update faq-functions.md

* Add binding explanation
main
Dan Abramov 7 years ago
committed by GitHub
parent
commit
986d97788c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 42
      content/docs/faq-ajax.md
  2. 131
      content/docs/faq-functions.md
  3. 6
      content/docs/faq-internals.md
  4. 17
      content/docs/faq-state.md
  5. 16
      content/docs/faq-structure.md
  6. 16
      content/docs/faq-styling.md

42
content/docs/faq-ajax.md

@ -31,27 +31,35 @@ The example API returns a JSON object like this:
```jsx
class MyComponent extends React.Component {
state = {
error: null,
isLoaded: false,
items: []
};
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
items: []
};
}
componentDidMount() {
fetch("https://api.example.com/items")
.then(res => res.json())
.then(result =>
this.setState({
isLoaded: true,
items: result.items
})
.then(
(result) => {
this.setState({
isLoaded: true,
items: result.items
});
},
// Note: it's important to handle errors here
// instead of a catch() block so that we don't swallow
// exceptions from actual bugs in components.
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
.catch(error =>
this.setState({
isLoaded: true,
error
})
);
}
render() {
@ -59,7 +67,7 @@ class MyComponent extends React.Component {
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading ...</div>;
return <div>Loading...</div>;
} else {
return (
<ul>

131
content/docs/faq-functions.md

@ -25,13 +25,13 @@ There are several ways to make sure functions have access to component attribute
```jsx
class Foo extends Component {
constructor () {
this.handleClick = this.handleClick.bind(this)
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log('Click happened')
console.log('Click happened');
}
render() {
return <button onClick={this.handleClick}>Click Me</button>
return <button onClick={this.handleClick}>Click Me</button>;
}
}
```
@ -40,11 +40,12 @@ class Foo extends Component {
```jsx
class Foo extends Component {
// Note: this syntax is experimental and not standardized yet.
handleClick = () => {
console.log('Click happened')
console.log('Click happened');
}
render() {
return <button onClick={this.handleClick}>Click Me</button>
return <button onClick={this.handleClick}>Click Me</button>;
}
}
```
@ -54,10 +55,10 @@ class Foo extends Component {
```jsx
class Foo extends Component {
handleClick () {
console.log('Click happened')
console.log('Click happened');
}
render() {
return <button onClick={this.handleClick.bind(this)}>Click Me</button>
return <button onClick={this.handleClick.bind(this)}>Click Me</button>;
}
}
```
@ -71,10 +72,10 @@ class Foo extends Component {
```jsx
class Foo extends Component {
handleClick () {
console.log('Click happened')
console.log('Click happened');
}
render() {
return <button onClick={() => this.handleClick()}>Click Me</button>
return <button onClick={() => this.handleClick()}>Click Me</button>;
}
}
```
@ -89,53 +90,86 @@ Generally speaking, yes, it is OK, and it is often the easiest way to pass param
If you do have performance issues, by all means, optimize!
### Why is binding necessary at all?
In JavaScript, these two code snippets are **not** equivalent:
```js
obj.method();
```
```js
var method = obj.method();
method();
```
Binding methods helps ensure that the second snippet works the same way as the first one.
With React, typically you only need to bind the methods you *pass* to other components. For example, `<button onClick={this.handleClick}>` passes `this.handleClick` so you want to bind it. However, it is unnecessary to bind the `render` method or the lifecycle methods: we don't pass them to other components.
[This post by Yehuda Katz](http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/) explains what binding is, and how functions work in JavaScript, in detail.
### Why is my function being called every time the component renders?
Make sure you aren't _calling the function_ when you pass it to the component:
```jsx
render() {
{/* handleClick is called instead of passed as a reference! */}
// Wrong: handleClick is called instead of passed as a reference!
return <button onClick={this.handleClick()}>Click Me</button>
}
```
Instead, *pass the function itself* (without parens):
```jsx
render() {
// Correct: handleClick is passed as a reference!
return <button onClick={this.handleClick}>Click Me</button>
}
```
### How do I pass a parameter to an event handler or callback?
You can use an arrow function to wrap around an event handler and pass parameters:
```jsx
<Element onClick={() => this.handleClick(id)} />
<button onClick={() => this.handleClick(id)} />
```
This is equivalent to calling `.bind`:
```jsx
<Element onClick={this.handleClick.bind(this, id)} />
<button onClick={this.handleClick.bind(this, id)} />
```
#### Example: Passing params using arrow functions
```jsx
const A = 65 // ASCII character code
class Alphabet extends React.Component {
state = {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.state = {
justClicked: null,
letters: Array.from({length: 26}, (_, i) => String.fromCharCode(A + i))
letters: Array.from({length: 26}, (_, i) => String.fromCharCode(A + i)).
};
}
handleClick(letter) {
this.setState({ justClicked: letter });
}
handleClick = letter => this.setState({ justClicked: letter })
render () {
return (
<div>
Just clicked: {this.state.justClicked}
<ul>
{ this.state.letters.map(letter =>
{this.state.letters.map(letter =>
<li key={letter} onClick={() => this.handleClick(letter)}>
{letter}
</li>
) }
)}
</ul>
</div>
)
@ -149,28 +183,33 @@ Alternately, you can use DOM APIs to store data needed for event handlers. Consi
```jsx
const A = 65 // ASCII character code
class Alphabet extends React.Component {
state = {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.state = {
justClicked: null,
letters: Array.from({length: 26}, (_, i) => String.fromCharCode(A + i))
};
}
handleClick = event => {
handleClick(e) {
this.setState({
justClicked: event.target.dataset.letter
})
justClicked: e.target.dataset.letter
});
}
render () {
render() {
return (
<div>
Just clicked: {this.state.justClicked}
<ul>
{ this.state.letters.map(letter =>
{this.state.letters.map(letter =>
<li key={letter} data-letter={letter} onClick={this.handleClick}>
{letter}
</li>
) }
)}
</ul>
</div>
)
@ -191,20 +230,26 @@ If you have an event handler such as `onClick` or `onScroll` and want to prevent
Throttling prevents a function from being called more than once in a given window of time. The example below throttles a "click" handler to prevent calling it more than once per second.
```jsx
import throttle from "lodash.throttle";
import throttle from 'lodash.throttle';
class LoadMoreButton extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.handleClickThrottled = throttle(this.handleClick, 1000);
}
componentWillUnmount() {
this._handleClick.cancel();
this.handleClickThrottled.cancel();
}
render() {
return <button onClick={this._handleClick}>Load More</button>;
return <button onClick={this.handleClickThrottled}>Load More</button>;
}
_handleClick = throttle(() => {
handleClick() {
this.props.loadMore();
}, 1000);
}
}
```
@ -213,33 +258,39 @@ class LoadMoreButton extends React.Component {
Debouncing ensures that a function will not be executed until after a certain amount of time has passed since it was last called. This can be useful when you have to perform some expensive calculation in response to an event that might dispatch rapidly (eg scroll or keyboard events). The example below debounces text input with a 250ms delay.
```jsx
import debounce from "lodash.debounce";
import debounce from 'lodash.debounce';
class Searchbox extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.emitChangeDebounced = debounce(this.emitChange, 250);
}
componentWillUnmount() {
this._handleChangeDebounced.cancel();
this.emitChangeDebounced.cancel();
}
render() {
return (
<input
type="text"
onChange={this._handleChange}
onChange={this.handleChange}
placeholder="Search..."
defaultValue={this.props.value}
/>
);
}
_handleChange = event => {
handleChange(e) {
// React pools events, so we read the value before debounce.
// Alternately we could call `event.persist()` and pass the entire event.
// For more info see reactjs.org/docs/events.html#event-pooling
this._handleChangeDebounced(event.target.value);
};
this.emitChangeDebounced(e.target.value);
}
_handleChangeDebounced = debounce(value => {
emitChange(value) {
this.props.onChange(value);
}, 250);
}
}
```

6
content/docs/faq-internals.md

@ -8,9 +8,11 @@ category: FAQ
### What is the Virtual DOM?
The virtual DOM (VDOM) is a programming concept where an ideal, or "virtual", representation of a UI is kept in memory and synced with the "real" DOM by a reconciliation engine/renderer (i.e. React Fiber + ReactDOM).
The virtual DOM (VDOM) is a programming concept where an ideal, or "virtual", representation of a UI is kept in memory and synced with the "real" DOM by a library such as ReactDOM. This process is called [reconciliation](/docs/reconciliation.html).
React uses the virtual DOM to enable its declarative API: You tell React what state you want the UI to be in, and it makes sure the DOM matches that state. This abstracts out the class manipulation, event handling, and manual DOM updating that you would otherwise have to use to build your app.
This approach enables the declarative API of React: You tell React what state you want the UI to be in, and it makes sure the DOM matches that state. This abstracts out the attribute manipulation, event handling, and manual DOM updating that you would otherwise have to use to build your app.
Since "virtual DOM" is more of a pattern than a specific technology, people sometimes say it to mean different things. In React world, the term "virtual DOM" is usually associated with [React elements](/docs/rendering-elements.html) since they are the objects representing the user interface. React, however, also uses internal objects called "fibers" to hold additional information about the component tree. They may also be considered a part of "virtual DOM" implementation in React.
### Is the Shadow DOM the same as the Virtual DOM?

17
content/docs/faq-state.md

@ -17,14 +17,15 @@ Calls to `setState` are asynchronous - don't rely on `this.state` to reflect the
Example of code that will not behave as expected:
```jsx
incrementCount = () => {
this.setState({count: this.state.count + 1})
incrementCount() {
// Note: this will *not* work as intended.
this.setState({count: this.state.count + 1});
}
handleSomething() {
// this.state.count is 1, then we do this:
this.incrementCount()
this.incrementCount() // state wasn't updated yet, so this sets 2 not 3
this.incrementCount();
this.incrementCount(); // state wasn't updated yet, so this sets 2 not 3
}
```
@ -39,16 +40,16 @@ Pass a function instead of an object to setState to ensure the call always uses
Passing an update function allows you to access the current state value inside the updater. Since `setState` calls are batched, this lets you chain updates and ensure they build on top of each other instead of conflicting:
```jsx
incrementCount = () => {
incrementCount() {
this.setState((prevState) => {
return {count: prevState.count + 1}
})
});
}
handleSomething() {
// this.state.count is 1, then we do this:
this.incrementCount()
this.incrementCount() // count is now 3
this.incrementCount();
this.incrementCount(); // count is now 3
}
```

16
content/docs/faq-structure.md

@ -8,18 +8,18 @@ category: FAQ
### Is there a recommended way to structure React projects?
One common way to structure projects is locate CSS, JSX, and tests together inside folders grouped by feature or route.
One common way to structure projects is locate CSS, JS, and tests together inside folders grouped by feature or route.
```
FeatureA
index.jsx
ComponentA.jsx
ComponentA.scss
index.js
ComponentA.js
ComponentA.css
ComponentA.test.js
Helper.jsx
Helper.js
Helper.test.js
FeatureB
index.jsx
ComponentB.jsx
ComponentB.test.jsx
index.js
ComponentB.js
ComponentB.test.js
```

16
content/docs/faq-styling.md

@ -16,6 +16,20 @@ render() {
}
```
It is common for CSS classes to depend on the component props or state:
```jsx
render() {
let className = 'menu';
if (this.props.isActive) {
className += ' menu-active';
}
return <span className={className}>Menu</span>
}
```
If you often find yourself writing code like this, [classnames](https://www.npmjs.com/package/classnames) package can simplify it.
### Can I use inline styles?
Yes, see the docs on styling [here](/docs/dom-elements.html#style).
@ -32,4 +46,4 @@ CSS-in-JS refers to a pattern where CSS is written with Javascript, then extract
### Can I do animations in React?
React can be used to power animations. See [React Transition Group](https://reactcommunity.org/react-transition-group/), for example.
React can be used to power animations. See [React Transition Group](https://reactcommunity.org/react-transition-group/) and [React Motion](https://github.com/chenglou/react-motion), for example.

Loading…
Cancel
Save