1

I am more familiar with NodeJs than react. I have build a react component that searches for user input and provides the output in a table format based on the value that the user has typed into the search input form. This is working as I want and the code for the module is below:

import React, { Component } from 'react';
import axios from 'axios';
import Suggestions from './Suggestions';

// API url
const API_URL = 'http://localhost:3000/api/file_infos'

class Search extends Component {
  state = {
    query: '',
    results: []
  }
  getCount = () => {
    axios.get(`${API_URL}count?filter[where][id][regexp]=/${this.state.query}/i`)
      .then(count => {
        this.setState({
          results: count.data
        })
      })
  }

  // query loop back API for matching queries base on text input
  getInfo = () => {
    axios.get(`${API_URL}?filter[where][id][regexp]=/${this.state.query}/i&filter[limit]=20`)
      .then(response => {
        this.setState({
          results: response.data
        })
      })
  }
  // check to see if input on the search bar has changed and update the search query accordingly 
  handleInputChange = () => {
    this.setState({
      query: this.search.value
    }, () => {
      if (this.state.query && this.state.query.length > 1) {
        if (this.state.query) {
          this.getInfo()
        }
      } else if (!this.state.query) {
      }
    })
  }
  // render form and pass results back to the home component 
  render() {
    return (
      <div>
      <form>
        <input
          placeholder="Search for..."
          ref={input => this.search = input}
          onChange={this.handleInputChange}
        />

      </form>

      <Suggestions results={this.state.results} />
      </div>
    )
  }
}

export default Search

The second module is the suggestions module that displays the output in the table format.

The next portion of the app I am building will open a file based on the table row that the user selected. I want that table data returned to a function so that I can make an http post request to my API that will in turn open the file using a NodeJS module.

I want the suggestions component to return the value of the data items in the table cells so that the data can be used to send to the API in order to open my files. The code I have come up with so far is only returning an undefined error.

Below is what I currently have:

import React from 'react';
// return results in a table format based on the text input entered 
 const Suggestions = (props) => {

   const state = {
        results: []
    }

    const handleFormOpen = () => {
        this.setState({
            results: this.results.value
        },
        console.log(this.state.results)
        )
    }

    const options = props.results.map(r => (
        <tr key={r.id} ref={tr => this.results = tr} onClick={handleFormOpen.bind(this)}>
            <td>{r.id}</td>
            <td>{r.OriginalPath}</td>
            <td>{r.CreateDate}</td>
            <td>{r.AccessDate}</td>
            <td>{r.WriteDate}</td>
            <td><i className="fas fa-book-open"></i></td>
        </tr>
    ))
    return <table className="striped responsive-table">
        <thead>
            <tr>
                <th>File Name</th>
                <th>Parent Directory</th>
                <th>Creation Date</th>
                <th>Access Date</th>
                <th>Write Date</th>
                <th>Open File</th>
            </tr>
        </thead>
        <tbody>
            {options}
        </tbody>
    </table>
}

export default Suggestions;

I am really unsure at this point if I am trying to tackle this issue in the correct way. I am thinking that maybe the suggestions component may need to be turned into a full class extending component but I am fairly lost at this point. Can someone please kindly point out my folly and get me going in the right direction?

UPDATE

As requested in the comments here is the error log from my browser:

Suggestions.js:10 Uncaught TypeError: Cannot read property 'results' of undefined
    at Object.handleFormOpen (Suggestions.js:10)
    at HTMLUnknownElement.callCallback (react-dom.development.js:145)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:195)
    at invokeGuardedCallback (react-dom.development.js:248)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:262)
    at executeDispatch (react-dom.development.js:593)
    at executeDispatchesInOrder (react-dom.development.js:615)
    at executeDispatchesAndRelease (react-dom.development.js:713)
    at executeDispatchesAndReleaseTopLevel (react-dom.development.js:724)
    at forEachAccumulated (react-dom.development.js:694)
    at runEventsInBatch (react-dom.development.js:855)
    at runExtractedEventsInBatch (react-dom.development.js:864)
    at handleTopLevel (react-dom.development.js:4857)
    at batchedUpdates$1 (react-dom.development.js:17498)
    at batchedUpdates (react-dom.development.js:2189)
    at dispatchEvent (react-dom.development.js:4936)
    at interactiveUpdates$1 (react-dom.development.js:17553)
    at interactiveUpdates (react-dom.development.js:2208)
    at dispatchInteractiveEvent (react-dom.development.js:4913)
3
  • Can you share the complete error log Commented Oct 10, 2018 at 18:08
  • For sure, post updated with log information. Commented Oct 10, 2018 at 18:10
  • Can you show us what you are getting from that console log of this.state.results Commented Oct 10, 2018 at 18:15

2 Answers 2

1

First thing Since your Suggestions component plays with state, I would recommend you to go with statefull component.

Stateless component is meant for getting props and returning jsx elements, there wont be any state mutations in stateless component. This is called pure function in javascript. Hope this makes clear.

Also since you declared handleFormOpen as an arrow function you no need to do binding. binding takes care automatically by arrow function. If you don't want to use arrow function and you want to bind it then do the binding always in constructor only but don't do binding anywhere in the component like you did in map.

PFB corrected Suggestions component code

import React, { Component } from 'react';
// return results in a table format based on the text input entered 
 export default class Suggestions extends Component {
  constructor(props){
    super(props);
    this.state = {
      results: [],
      value: ""
    }
  }


  handleFormOpen = (path, id) => {
    console.log("id", id, path);//like wise pass value to this function in .map and get the value here
      this.setState({
          value: id
      });
  }


    render(){ 
      const { results } = this.props;
      return (<div>
        <table className="striped responsive-table">
          <thead>
              <tr>
                  <th>File Name</th>
                  <th>Parent Directory</th>
                  <th>Creation Date</th>
                  <th>Access Date</th>
                  <th>Write Date</th>
                  <th>Open File</th>
              </tr>
          </thead>
          <tbody>
              {Array.isArray(results) && results.length > 0 && results.map(r => (
                <tr key={r.id} ref={tr => this.results = tr} onClick={() => this.handleFormOpen(r.OriginalPath, r.id)}>
                    <td>{r.id}</td>
                    <td>{r.OriginalPath}</td>
                    <td>{r.CreateDate}</td>
                    <td>{r.AccessDate}</td>
                    <td>{r.WriteDate}</td>
                    <td><i className="fas fa-book-open"></i></td>
                </tr>
              ))}
          </tbody>
        </table>
      </div>)
    }    
}

export default Suggestions;
Sign up to request clarification or add additional context in comments.

7 Comments

This gets me much closer than I was before. I appreciate you taking the time for the detailed explanation. The event is not firing any more when the row is clicked and the console.log is being generated based on the values of the query instead of the clicked results but I am going to try to tackle this problem on my own. Cheers!
You are welcome. The handleFormOpen event handler function only gets trigger if your data contains value. I added as an example of how to get value when click happens. I am not sure which field in your results array contains the value so just for eg I added as r.value in my answer. If you can let me know what are the values you need in handleFormOpen I can help you on that
You're an amazing teacher, I was able to figure it out based on the binding knowledge you bestowed on me. The issue was that I was not using the arrow function on the click event. When I do so, the correct information is being logged and I can now pass that to my post request. It's really a thing of beauty. onClick={() => this.handleFormOpen(r.OriginalPath, r.id)}
hooo yeah I do missed that. Glad to help you. Great to see you fixed it so quickly. Cheers👍
Sorry, I did upvote but got side tracked at an offsite meeting yesterday. I have accepted the answer now.
|
0

You are using states in Functional Component, You need to use React Component

import React from 'react';
// return results in a table format based on the text input entered 
 class Suggestions extends React.Component {
   constructor(props) {
     super(props);
     this.state = {
       results: [],
     }
   }


    handleFormOpen = () => {
      this.setState({
          results: this.results.value
      },
      console.log(this.state.results)
      )
    }

    render () {
      const options = this.props.results.map(r => (
          <tr key={r.id} ref={tr => this.results = tr} onClick={handleFormOpen.bind(this)}>
              <td>{r.id}</td>
              <td>{r.OriginalPath}</td>
              <td>{r.CreateDate}</td>
              <td>{r.AccessDate}</td>
              <td>{r.WriteDate}</td>
              <td><i className="fas fa-book-open"></i></td>
          </tr>
      ))
      return (
        <table className="striped responsive-table">
            <thead>
                <tr>
                    <th>File Name</th>
                    <th>Parent Directory</th>
                    <th>Creation Date</th>
                    <th>Access Date</th>
                    <th>Write Date</th>
                    <th>Open File</th>
                </tr>
            </thead>
            <tbody>
                {options}
            </tbody>
        </table>
      )
    }
}

export default Suggestions;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.