【问题标题】:Is there a special method in React that updates DOM?React 中是否有更新 DOM 的特殊方法?
【发布时间】:2019-11-25 14:45:28
【问题描述】:

您好,我正在 React 中制作一个抽认卡应用程序,我正在尝试在卡片之间切换,但在我切换卡片之前它们不会更新。

我尝试将索引 currentCard 设置为 state 而不是全局,但我在实现它时遇到了一些问题。我也尝试了 this.forceUpdate(),但结果要么未定义。

import React from 'react';
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';

// variables
let currentCard = 0;

这是我从这里获得卡片的地方:

const mockData = [
  {
    front: "Hello",
    back: "Dobrý den"
  },
  {
    front: "How are you?",
    back: "Jak se máš?"
  },
  {
    front: "I'm fine",
    back: "Mám se dobře"
  }

];

class LeftArrow extends React.Component {
  constructor(props){
    super(props);
    this.state = {isClicked: false};
  }

  render(){
    //checks it so it can't be less than zero
    return(
      <button
      className="btn btn-primary"
      onClick={() => this.props.onCardChange('LEFT')}
      >&lt;</button>
    )
  }
}

class RightArrow extends React.Component {
  constructor(props){
    super(props);
    this.state = {isClicked: false};
  }

  render(){
    // checks it so it isn't more than the length of array
    // checks if card has
    return(
      <button
      className="btn btn-primary"
      onClick={() => this.props.onCardChange('RIGHT')}
      >
      &gt;
      </button>
    )
  }
}

class Card extends React.Component {
  constructor(props){
    super(props);
    // helps toggle between the front face and the back
    this.state = {
      isFront: true,
    };
  } 

这是我在有人点击箭头时使用的方法:

  handleCardChange(direction) {
    if(direction === 'RIGHT'){
      console.log(direction);
      if(currentCard < mockData.length - 1){
        currentCard += 1;
      } else if (currentCard == mockData.length - 1) {
        currentCard = 0;
      }
    }

    if (direction === 'LEFT') {
      if (currentCard > 0) {
        currentCard -= 1;
      } else if (currentCard == 0) {
        currentCard = mockData.length - 1;
      }
    }
  }

  render(){
    // if clicked, isFront changes to the opposite
    // if isFront is true, show front, if not, show back
    console.log(this.state.wasTurned, currentCard);
    return (
      // , wasTurned: !this.state.wasTurned
      <div className="App">
        <div
        className="Card"
        onClick={() => this.setState({
          isFront: !this.state.isFront,
          wasTurned: true
        })}
        >
          {this.state.isFront ? mockData[currentCard].front : mockData[currentCard].back}
        </div>
        <div className="arrow_panel">
          <LeftArrow onCardChange={this.handleCardChange}/><RightArrow onCardChange={this.handleCardChange}/>
        </div>
      </div>
    );
  }
}

export default Card; 

我预计卡片会自动更新,因此当我点击箭头时,它会显示下一张卡片的正面/背面,但您必须再次点击卡片才能看到下一张卡片。非常感谢您阅读到这里,并从您忙碌的一天中抽出宝贵的时间来帮助我。

// variables
let currentCard = 0;
const mockData = [
  {
    front: "Hello",
    back: "Dobrý den"
  },
  {
    front: "How are you?",
    back: "Jak se máš?"
  },
  {
    front: "I'm fine",
    back: "Mám se dobře"
  }

];

class LeftArrow extends React.Component {
  constructor(props){
    super(props);
    this.state = {isClicked: false};
  }

  render(){
    //checks it so it can't be less than zero
    return(
      <button
      className="btn btn-primary"
      onClick={() => this.props.onCardChange('LEFT')}
      >&lt;</button>
    )
  }
}

class RightArrow extends React.Component {
  constructor(props){
    super(props);
    this.state = {isClicked: false};
  }

  render(){
    // checks it so it isn't more than the length of array
    // checks if card has
    return(
      <button
      className="btn btn-primary"
      onClick={() => this.props.onCardChange('RIGHT')}
      >
      &gt;
      </button>
    )
  }
}

class Card extends React.Component {
  constructor(props){
    super(props);
    // helps toggle between the front face and the back
    this.state = {
      isFront: true,
    };
  }

  handleCardChange(direction) {
    if(direction === 'RIGHT'){
      console.log(direction);
      if(currentCard < mockData.length - 1){
        currentCard += 1;
      } else if (currentCard == mockData.length - 1) {
        currentCard = 0;
      }
    }

    if (direction === 'LEFT') {
      if (currentCard > 0) {
        currentCard -= 1;
      } else if (currentCard == 0) {
        currentCard = mockData.length - 1;
      }
    }
  }

  render(){
    // if clicked, isFront changes to the opposite
    // if isFront is true, show front, if not, show back
    console.log(this.state.wasTurned, currentCard);
    return (
      // , wasTurned: !this.state.wasTurned
      <div className="App">
        <div
        className="Card"
        onClick={() => this.setState({
          isFront: !this.state.isFront,
          wasTurned: true
        })}
        >
          {this.state.isFront ? mockData[currentCard].front : mockData[currentCard].back}
        </div>
        <div className="arrow_panel">
          <LeftArrow onCardChange={this.handleCardChange}/><RightArrow onCardChange={this.handleCardChange}/>
        </div>
      </div>
    );
  }
}


ReactDOM.render(<Card />, document.getElementById('root'));
.App {
  text-align: center;
}

.Card {
  margin: 0 auto;
  width: 50%;
  padding: 50px;
  border: 1px solid black;
  border-radius: 5px;
  font-size: 40px;
}

.arrow_panel button {
  margin: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="theme-color" content="#000000" />
  <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
  <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
  <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
  <title>React App</title>
</head>

<body>
  <noscript>You need to enable JavaScript to run this app.</noscript>
  <div id="root"></div>
  <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
</body>

</html>

【问题讨论】:

  • 您好,欢迎来到 Stack Overflow!你能把你的帖子缩小一点,只包含与你的问题相关的代码吗?对于许多人来说,这可能有点难以承受......
  • 您使用setState() 组件方法更新组件的状态数据。以这种方式更新组件的状态将重新渲染该组件的 DOM。

标签: javascript reactjs ecmascript-6


【解决方案1】:

您必须将 mockData 和 currentCard 置于 Card 组件的状态,handleCardChange 应使用 this.setState({}) 更新状态。

const mockData = [
  {
    front: "Hello",
    back: "Dobrý den"
  },
  {
    front: "How are you?",
    back: "Jak se máš?"
  },
  {
    front: "I'm fine",
    back: "Mám se dobře"
  }
];

class Card extends React.Component {
  constructor(props) {
    super(props);
    // helps toggle between the front face and the back
    this.state = {
      isFront: true
      currentCard: 0,
      mockData,
    };
  }

【讨论】:

    【解决方案2】:

    使用 setState

    this.setState({someState: "someNewState"})
    

    【讨论】:

      猜你喜欢
      • 2017-09-29
      • 1970-01-01
      • 2015-09-08
      • 1970-01-01
      • 2020-01-10
      • 1970-01-01
      • 1970-01-01
      • 2013-04-18
      相关资源
      最近更新 更多