yuvi
yuvi

Reputation: 18457

Meteor React tutorial interacting with mongo not working

I have been trying for a while to learn how to build mobile apps with Javascript, and honestly I have no idea how anyone is able to do anything. Everything is broken. Every tutorial I've tried has failed to work for some bizarre reason. I am at my wits end.

I've finally decided to try and be even simpler, and just do the most basic tutorial I can find. What could go wrong. Well, it only took 3 pages of almost no code to completely stop working. I've done this, and I cannot insert anything to my db. My app fetches no data. When trying to add a new task, it gets added then disappears almost immediately, with a message stating insert failed: Method '/tasks/insert' not found (not even an error with some traceback).

The code really couldn't be simpler:

// imports/api/tasks.js

import { Mongo } from 'meteor/mongo';

export const Tasks = new Mongo.Collection('tasks');

// imports/ui/App.js

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { withTracker } from 'meteor/react-meteor-data'

import { Tasks } from '../api/tasks.js';

import Task from './Task.js';

// App component - represents the whole app
class App extends Component {
    handleSubmit(event) {
        event.preventDefault();

        // find the text field via the react ref
        const text = ReactDOM.findDOMNode(this.refs.textInput).value.trim();
        Tasks.insert({ text, createdAt: new Date() });

        // Clear form
        ReactDOM.findDOMNode(this.refs.textInput).value = '';
    }

    renderTasks() {
        return this.props.tasks.map((task) => (
          <Task key={task._id} task={task} />
        ));
    }

    render() {
        return (
          <div className="container">
            <header>
              <h1>Todo List</h1>
                <form className="new-task" onSubmit={this.handleSubmit.bind(this)} >
                    <input
                        type="text"
                        ref="textInput"
                        placeholder="Type to add new tasks"
                    />
                </form>
            </header>

            <ul>
              {this.renderTasks()}
            </ul>
          </div>
        );
    }
};

export default withTracker(() => {
  return {
    tasks: Tasks.find({}).fetch(),
  };
})(App);

What is wrong? What am I missing?

Upvotes: 0

Views: 257

Answers (1)

Jankapunkt
Jankapunkt

Reputation: 8423

The tutorial is indeed out of date and should be updated.

Background

In June 2017 there was a big security issue with allow/deny identified and the feature has been blocked since then.

Meteor allowed you to define client collection, that automatically synced with the server when the methods insert, update, remove were called on the client.

In order to control the access permissions, the allow/deny feature was implemented.

Now without allow/deny you will get the insert failed: Method '/tasks/insert' not found when classing SomeCollectionOnClient.insert but since this feature is obsolete (you will even get a big warning when setting it up), you need to create a server side method and call it from the client in order resolve this issue:

On the server create this method and ensure it is in the import chain from server/main.js:

new ValidatedMethod({
  name: 'tasks.insert',
  validate(args) {
    // better use simpl-schema here
    if (!args.text || !args.createdAt) {
      throw new Meteor.Error('incompleteArgs', 'args are incomplete')
    }
  },
  run (args) {
    // check user permissions...
    return Tasks.insert({ text, createdAt })
  }
})

In your client component you can then call it via:

// find the text field via the react ref
const text = ReactDOM.findDOMNode(this.refs.textInput).value.trim();
Meteor.call('tasks.insert', {text, createdAt: new Date()}, (err, res) => {
  // do something on err / on res
})

Note that this couples your component to the server side method and you may rather try to implement some containers for your pages that handle all the connection / pub-sub / method calling activity wile your components solely render content.

More to read / used in this answer:

https://guide.meteor.com/react.html

https://guide.meteor.com/security.html

https://docs.meteor.com/api/methods.html#Meteor-call

https://guide.meteor.com/methods.html#validated-method

Upvotes: 1

Related Questions