React 面试必知必会 Day2

1,439 阅读5分钟

大家好,我是 @洛竹

本文首发于 洛竹的官方网站

本文翻译自 sudheerj/reactjs-interview-questions

本文同步于公众号洛竹早茶馆,转载请联系作者。

1. 为什么我们不能直接更新状态?

如果你尝试直接更新状态,React 组件并不会重新渲染。

// 错误❌
this.state.message = 'Hello world';

正确的做法是使用 setState() 方法。它会计划一个对组件状态对象的更新。当状态更改时,组件通过重新渲染进行响应。

// 正确✅
this.setState({ message: 'Hello World' });

**注意:**你可以使用构造函数或者最新的 javascript class 字段声明语法直接将其分配给状态对象。

2. 回调函数作为 setState() 的参数的目的是什么?

setState 完成并重新渲染组件后,将调用回调函数。由于 setState() 是异步的,因此回调函数可用于任何后续操作。

**注意:**我们建议使用生命周期方法而不是这个回调函数

setState({ name: 'John' }, () =>
  console.log('The name has updated and component re-rendered'),
);

3. HTML 和 React 的事件处理有什么不同?

下面是一些 HTML 和 React 的事件处理的主要不同:

  1. 在 HTML 中,事件名应该是全小写的:
<button onclick="activateLasers()"></button>

然而在 React 中事件名遵循小驼峰 格式:

<button onClick={activateLasers}>
  1. 在 HTML 中,你应该返回 false 来阻止默认行为:
<a href="#" onclick='console.log("The link was clicked."); return false;' />

然后在 React 中你必须明确地调用 preventDefault()

function handleClick(event) {
  event.preventDefault();
  console.log('The link was clicked.');
}
  1. 在 HTML 中,你调用函数时需要加上 ()

然后在 React 中你不应该在函数名后带上 ()。(比如前面示例中的 activateLasers 函数)

4. 如何在 JSX 回调函数中绑定方法或事件处理器

这里有 3 个方法做到这一点:

  1. 在构造器中绑定: 在 JavaScript 类中,默认情况下不绑定方法。同样的事情也适用于定义为类方法的 React 事件处理器。通常我们将它们绑定在构造函数中。
class Component extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    // ...
  }
}
  1. 类的公共字段语法: 如果你不喜欢使用绑定的方式,也可以使用类的公共字段语法来正确绑定回调:
handleClick = () => {
  console.log('this is:', this);
};
<button onClick={this.handleClick}>{'Click me'}</button>
  1. 箭头函数作为回调: 你可以直接在回调中使用箭头函数
<button onClick={event => this.handleClick(event)}>{'Click me'}</button>

注意: 如果回调作为 prop 传递给子组件,这些组件可能会触发额外的重渲染。在这些场景中,考虑到性能因素,最佳的选择是使用 .bind() 或类的公共字段语法。

5. 如何传递参数给事件处理器或回调?

你可以使用一个箭头函数来包裹一个事件处理器并传递参数:

<button onClick={() => this.handleClick(id)} />

这等价于调用 .bind 函数:

<button onClick={this.handleClick.bind(this, id)} />

除了这两种办法,你也可以传递参数给一个箭头函数:

<button onClick={this.handleClick(id)} />;
handleClick = id => () => {
  console.log('Hello, your ticket number is', id);
};

6. React 中的合成事件是什么?

SyntheticEvent 是基于浏览器本地事件的跨浏览器包装。它的 API 与浏览器的本地事件相同,包括 stopPropagation()preventDefault(),但事件在所有浏览器中的表现均一致。

7. 什么是内联条件表达式?

你可以使用 JS 可用的 if 语句或三元表达式来有条件地渲染表达式。 除了这些方法之外,还可以通过将所有表达式括在花括号中然后在其后跟JS逻辑运算符 && 来将任何表达式嵌入JSX。

<h1>Hello!</h1>;
{
  messages.length > 0 && !isLogin ? (
    <h2>You have {messages.length} unread messages.</h2>
  ) : (
    <h2>You don't have unread messages.</h2>
  );
}

8. 什么是 key prop?在元素数组中使用它的好处是什么?

key 是当你创建一个元素数组时应该包含的一个特殊的字符串属性。key prop 会帮助 React 识别具体哪一项被修改、添加或被移除。

通常,我们将数据中的 ID 用作 key

const todoItems = todos.map(todo => <li key={todo.id}>{todo.text}</li>);

如果呈现的项目没有稳定的 ID,退而求其次,我们可以将 index 作为 key

const todoItems = todos.map((todo, index) => <li key={index.toString()}>{todo.text}</li>);

注意:

  1. 如果列表项可能改变,不建议使用 indexes 作为 keys。这可能会对性能产生负面影响,并可能导致组件状态出现问题。
  2. 如果你将列表项提取为单独的组件,则在列表组件上应用 keys 而不是 li 标签。
  3. 如果列表项中不存在 key prop,则控制台中将出现警告消息。

9. refs 有什么用?

refs 用于返回对该元素的引用。在大多数情况下,应避免使用它们,但是,当你需要直接访问 DOM 元素或组件的实例时,它们会很有用。

10. 如何创建 refs?

这里有两种方式

1.这是最近添加的方法。使用 React.createRef() 方法创建 refs,并通过 ref 属性附加到 React 元素。为了在整个组件中使用 refs,只需将ref 分配给构造函数中的 instance 属性。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return <div ref={this.myRef} />;
  }
}
  1. 无论 React 版本如何,你都可以使用 ref 回调方法。例如,搜索栏组件的输入元素的访问方式如下。
class SearchBar extends Component {
  constructor(props) {
    super(props);
    this.txtSearch = null;
    this.state = { term: '' };
    this.setInputSearchRef = e => {
      this.txtSearch = e;
    };
  }
  onInputChange(event) {
    this.setState({ term: this.txtSearch.value });
  }
  render() {
    return (
      <input
        value={this.state.term}
        onChange={this.onInputChange.bind(this)}
        ref={this.setInputSearchRef}
      />
    );
  }
}

你也可以使用闭包在函数组件中使用 refs。

注意: 你也可以使用内联 ref 回调,即使这不是推荐的方法