You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何从W3 Schools借鉴的typeWriter函数报‘not defined’错误?

Fixing "typeWriter is not defined" Error in React Typewriter Effect & Understanding Recursive Calls

Let's break down your problem step by step—first fixing that frustrating "typeWriter is not defined" error, then clearing up the confusion around the recursive function logic from the tutorial.

1. Why You're Seeing the Error

In your React component, typeWriter is an instance method (defined as an arrow function on the Hero class). When you pass typeWriter directly to setTimeout, JavaScript loses track of your component's context and tries to find a global function with that name (which doesn't exist—unlike the vanilla JS tutorial example, which uses a global function).

On top of that, your i variable is declared inside the typeWriter function, so it resets to 0 every time the function runs. That means you'd only ever print the first character of your message, even if the error was fixed!

2. Corrected Component Code

Here's the fixed version with key changes explained:

import React, { Component } from 'react';
class Hero extends Component {
  // Move tracking variables to the component instance so they persist between calls
  i = 0;
  message = 'I want to hike';
  speed = 50;

  componentDidMount = () => {
    this.typeWriter();
  }

  typeWriter = () => {
    if (this.i < this.message.length) {
      document.getElementById('typewriter-effect').innerHTML += this.message.charAt(this.i);
      this.i++;
      // Use an arrow function to preserve the component's `this` context
      setTimeout(() => this.typeWriter(), this.speed);
    }
  }

  render() {
    return (
      <div className='banner-container'>
        <h1>iHike</h1>
        <h3>Find your adventure</h3>
        <p id='typewriter-effect'></p>
      </div>
    )
  }
}
export default Hero;

What Changed:

  • Instance-level variables: i, message, and speed are now attached to the component instance (this.i instead of a local i). This keeps their values between calls to typeWriter, so we can track how many characters we've printed.
  • Arrow function in setTimeout: () => this.typeWriter() ensures that when the timeout triggers, it calls the typeWriter method on your component instance, not searching for a global function.

3. Understanding the Recursive "Self-Invocation"

The tutorial's code uses recursion (the function calling itself) to create the typing effect. In vanilla JS, since the function is global, setTimeout(typeWriter, speed) works directly. But in React, methods are tied to component instances, so you need to explicitly reference this.typeWriter—and preserve the this context with an arrow function (or bind the method beforehand).

Each call to typeWriter adds one character, increments the counter, and schedules the next call via setTimeout. This repeats until all characters are printed.

Bonus: A More React-Friendly Approach

Instead of manipulating the DOM directly with document.getElementById, you can use React state to manage the displayed text—this is more aligned with React's data-driven philosophy:

import React, { Component } from 'react';
class Hero extends Component {
  state = {
    displayedText: '',
    message: 'I want to hike',
    speed: 50
  };

  componentDidMount() {
    this.typeWriter();
  }

  typeWriter = () => {
    const { displayedText, message, speed } = this.state;
    if (displayedText.length < message.length) {
      this.setState(prevState => ({
        displayedText: prevState.displayedText + message.charAt(prevState.displayedText.length)
      }), () => {
        // Schedule next call after state updates
        setTimeout(() => this.typeWriter(), speed);
      });
    }
  }

  render() {
    return (
      <div className='banner-container'>
        <h1>iHike</h1>
        <h3>Find your adventure</h3>
        <p>{this.state.displayedText}</p>
      </div>
    )
  }
}
export default Hero;

This version uses React state to track the text, so React handles updating the UI automatically when the state changes—no direct DOM manipulation needed.

内容的提问来源于stack exchange,提问作者user8672583

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:07:30