简体   繁体   中英

Meteor: Using methods from react classes

In meteor, how do I use a method inside a react class?

I want to trigger a method inside a react class with a keypress, but cant seem to access it with class.method()

In toolbar.js:

import React, { Component } from 'react';

class Toolbar extends Component {
  addSection(){
    alert("add section");
  };
  render(){
    return (
      <div className="toolbar">
        <button onClick={this.addSection.bind(this)}>add section</button>
      </div>
    );
  }
}

export default Toolbar;

In main.js:

import React from 'react';
import ReactDOM from 'react-dom';
import Toolbar from './components/toolbar';

const App = () => {
  return (
    <div>
        <Toolbar />
    </div>
  );
};

Meteor.startup(() => {
  ReactDOM.render(<App />, document.querySelector('.container'));
  $(document).on('keyup', function(e) {
    if (e.ctrlKey && e.keyCode == 49) { // ctrl+1
      Toolbar.addSection(); //errormsg: toolbar.addsection is not a function
    }
  });
});

Any help is greatly appreciated. Thank you

First , This is React - If you ever find yourself using jQuery, you're probably doing it wrong.

Second , (and this might just be my opinion) but you should always keep things that are related to a component contained within the component. It's cleaner and you don't have to go all around your application just to figure out where that keypress is happening. It should be as close to the code using it or displaying it as possible.

Third , You need to be aware when your component has mounted, and when that component is not on the screen. Maybe your ctrl+1 doesn't become relevant until later on after somebody has "logged in" or something. So your eventListener should mount and dismount with the component using it.

class Application extends React.Component {
  constructor(props) {
    super(props)

    this.addSection     = this.addSection.bind(this)     // This is not "needed" - but I'm doing it anyways because I can.
    this.keydownHandler = this.keydownHandler.bind(this) // See comment from @dfsq
  }

  componentDidMount() {
    document.addEventListener('keydown', this.keydownHandler)
  }

  componentWillUnmount() {
    document.removeEventListener('keydown', this.keydownHandler)
  }

  addSection() {
    alert("add section")
  }

  keydownHandler(event) {
    if(event.keyCode===49 && event.ctrlKey)
      this.addSection()
  }

  render() {
    return (
      <div>
        <p>Press Ctrl+1</p>
      </div>
    )
  }
}

Here is a working CodePen.


To use your code as an example:

in toolbar.js :

import React, { Component } from 'react';

class Toolbar extends Component {
  constructor(props) {
    super(props)

    this.addSection     = this.addSection.bind(this)     // This is not "needed" - but I'm doing it anyways because I can.  I think from now on I'm going to bind all of my functions like this.  Any comment on this would be interesting.
    this.keydownHandler = this.keydownHandler.bind(this) // See comment from @dfsq
  }

  componentDidMount() {
    document.addEventListener('keydown', this.keydownHandler)
  }

  componentWillUnmount() {
    document.removeEventListener('keydown', this.keydownHandler)
  }

  addSection() {
    alert("add section")
  }

  keydownHandler(event) {
    if(event.keyCode===49 && event.ctrlKey)
      this.addSection()
  }

  render(){
    return (
      <div className="toolbar">
        <button onClick={this.addSection.bind(this)}>add section</button>
      </div>
    )
  }
}

export default Toolbar;
  1. add ReactJS Lifecycle Functions
  2. add constructor to fix the React, removeEventListener and bind(this) gotcha ... here is some more reading on this

in main.js :

import React from 'react'
import ReactDOM from 'react-dom'
import Toolbar from './components/toolbar'

const App = () => {
  return (
    <div>
        <Toolbar />
    </div>
  )
}

Meteor.startup(() => {
  ReactDOM.render(<App />, document.querySelector('.container'))
})

I feel it important to stress a key concept in this answer. As a rule of thumb in React, if you're using jQuery, you're probably doing it wrong. React is designed very well and usually, there are very good design decisions that went into why React works the way that it does. So, if you need to use jQuery for a little bit, while you're still learning React, that's okay (I did it too for a few days shhh... don't tell anyone ). But, I think that in the long run, you will find that after a while you really have no need for jQuery when you're using React properly.

Another thing. StackOverflow is great, but sometimes other venues are more appropriate for certain types of questions and advice. Two communities that have really helped me are the Meteor Forums and this React Chatroom . Both communities are Extremely friendly. If you ever go to the Reactiflux help channel, say hi to Acemarke for me (he basically lives there) - at first, I seriously thought he was some kind of AI that Facebook designed to answer questions about React (I'm not joking, I actually thought for a while until his notable friendly humor kicked in).

Also, as a style note (and this is completely opinion) - stop using semicolons. It's okay now . You actually have to make less decisions if you just stop using them. Try it for a week and you'll see the light.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM