【问题标题】:Javascript in react function when component is mounted安装组件时反应功能中的Javascript
【发布时间】:2020-05-07 12:41:17
【问题描述】:

我的键盘可以正常工作,但现在我正在为状态处理实现 redux。我的旧版本作为类组件工作,并且在 componentDidMount 上调用了 javascript 函数。现在这不再是一个选项,因为我现在需要将它转换为一个函数,以使其与 redux 的调度一起工作。我尝试将 javascript 放在 return 下并将其作为单独的函数调用,两者都没有做任何事情。有没有办法做到这一点?

import React from 'react';
import '../../style/App.scss';
import $ from "jquery";
import { UPDATE_GAME_STATE } from '../../actions'
import { useDispatch } from 'react-redux';

function Keypad(){
  init_keypad();
  return(
  <div className="keypad_wrapper">
    <div className="screen"></div>
    <div className="error notification">ERROR</div>
    <div className="success notification">SUCCESS</div>

    <div className="key">1</div>
    <div className="key">2</div>
    <div className="key">3</div>
    <div className="key">4</div>
    <div className="key">5</div>
    <div className="key">6</div>
    <div className="key">7</div>
    <div className="key">8</div>
    <div className="key">9</div>
    <div className="key last">0</div>
  </div>
);
}
export default Keypad;


function init_keypad(){
  const dispatch = useDispatch();
  window.tries = 0;
  $(".key").click(function(){
    var n = $(this).html();
    $('.screen').append( n );
    window.tries++;
    // if 4 digits are entered check if its correct
    if (window.tries >= 4){
      var w = $('.screen').html();
      if (w == 1234){
        $('.success').show().delay(5000).queue(function(n) {
          $('.success').hide(); n();
          dispatch(UPDATE_GAME_STATE('playing'));
        });
      }
      else{
        $('.error').show().delay(1000).queue(function(n) {
          $('.error').hide(); n();
        });
      }
      $('.screen').html('');
      window.tries = 0;
    }
  });
}

错误信息现在是这样的:

React Hook "useDispatch" 在函数 "init_keypad" 中被调用,该函数既不是 React 函数组件也不是自定义 React Hook 函数 react-hooks/rules-of-hooks

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    首先你需要在 React 组件中使用 useDispatch 而不是普通函数,在这种情况下是 Keypad

    你需要将它包裹在 useEffect 中,因为它相当于类组件中的 componentDidMount

    import React, { useEffect } from "react";
    
    function Keypad(){
       useEffect(() => {
          init_keypad();
       }, []);
    
       return (
        ...
       );
    }
    

    【讨论】:

    • 谢谢,这就是我所需要的!
    【解决方案2】:

    你需要在 react 组件中使用钩子,在你使用 useDispatch 时不会发生这种情况,所以在这里你可以通过两种方式将 init_keypad 设为 react 功能组件,然后使用useDispatch 或者简单地从 Keypad

    传递 useDipatch
    import React from 'react';
    import '../../style/App.scss';
    import $ from "jquery";
    import { UPDATE_GAME_STATE } from '../../actions'
    import { useDispatch, useEffect } from 'react-redux';
    
    function Keypad(){
      const dispatch = useDispatch();
       useEffect(() => {
         init_keypad(dispatch);
       }, []);      
    return(
      <div className="keypad_wrapper">
        <div className="screen"></div>
        <div className="error notification">ERROR</div>
        <div className="success notification">SUCCESS</div>
    
        <div className="key">1</div>
        <div className="key">2</div>
        <div className="key">3</div>
        <div className="key">4</div>
        <div className="key">5</div>
        <div className="key">6</div>
        <div className="key">7</div>
        <div className="key">8</div>
        <div className="key">9</div>
        <div className="key last">0</div>
      </div>
    );
    }
    export default Keypad;
    
    
    function init_keypad(dispatch){
      window.tries = 0;
      $(".key").click(function(){
        var n = $(this).html();
        $('.screen').append( n );
        window.tries++;
        // if 4 digits are entered check if its correct
        if (window.tries >= 4){
          var w = $('.screen').html();
          if (w == 1234){
            $('.success').show().delay(5000).queue(function(n) {
              $('.success').hide(); n();
              dispatch(UPDATE_GAME_STATE('playing'));
            });
          }
          else{
            $('.error').show().delay(1000).queue(function(n) {
              $('.error').hide(); n();
            });
          }
          $('.screen').html('');
          window.tries = 0;
        }
      });
    }
    

    【讨论】:

      【解决方案3】:

      您可以使用“useEffect”钩子将其用作等效的componentDidMount,并避免使用窗口对象来跟踪计数,而是使用“useRef”钩子,如下所示

          import React from 'react';
          import '../../style/App.scss';
          import $ from "jquery";
          import { UPDATE_GAME_STATE } from '../../actions'
          import { useDispatch } from 'react-redux';
      
          function Keypad() {
              const dispatch = useDispatch();
              const tries = React.useRef(0);
      
              React.useEffect(() => {
                  $(".key").click(function () {
                      var n = $(this).html();
                      $('.screen').append(n);
                      tries.current++;
                      // if 4 digits are entered check if its correct
                      if (tries.current >= 4) {
                          var w = $('.screen').html();
                          if (w == 1234) {
                              $('.success').show().delay(5000).queue(function (n) {
                                  $('.success').hide(); n();
                                  dispatch(UPDATE_GAME_STATE('playing'));
                              });
                          }
                          else {
                              $('.error').show().delay(1000).queue(function (n) {
                                  $('.error').hide(); n();
                              });
                          }
                          $('.screen').html('');
                          tries.current = 0;
                      }
                  });
              }, []);
      
              return (
                  <div className="keypad_wrapper">
                      <div className="screen"></div>
                      <div className="error notification">ERROR</div>
                      <div className="success notification">SUCCESS</div>
      
                      <div className="key">1</div>
                      <div className="key">2</div>
                      <div className="key">3</div>
                      <div className="key">4</div>
                      <div className="key">5</div>
                      <div className="key">6</div>
                      <div className="key">7</div>
                      <div className="key">8</div>
                      <div className="key">9</div>
                      <div className="key last">0</div>
                  </div>
              );
          }
          export default Keypad;
      
      

      但是,我还建议您不要将 jQuery 与 ReactJs 一起使用,因为您使用 jQuery 等库直接操作/玩 DOM 对象时失去了使用 ReactJs 的主要目的。

      同时使用 jQuery 和 RaectJs 是一种不好的做法,因为 React 使用了一个称为虚拟 DOM 的概念,而不是实际的 DOM。 React 不知道在这个 Virtual DOM 之外所做的更改。当您使用 jQuery 或任何其他操作实际 DOM 的库时,您的应用程序可能会不同步。

      如果您想将 jQuery 用于 AJAX,您可以使用专门为 AJAX 制作的库,例如 Axios 或本机 Fetch API。

      并且不要忘记在卸载时移除事件监听器,为此您可以在 useEffect 挂钩中返回一个函数,该函数的行为类似于 componentWillUnmount 方法

      【讨论】:

        猜你喜欢
        • 2021-03-13
        • 1970-01-01
        • 2021-06-18
        • 1970-01-01
        • 2020-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多