3

I want to display a list of Dogs with a search bar above which when typed in will only display the dogs which meet the criteria.

I previously had the array stored in state and everything was working fine. However now, looking forward once up and running I will have thousands of entries inside of the array and it will get too messy. So I have decided that I wish to store all of my objects in JSON format as it will be a lot easier to manage I believe.

I'm stuck, I have tried to integrate the .json file into the old format but I am not getting any data come up and when I type in the searchbar i get an error message.

here is my json:

[
 {
  "id": 3,
  "title": "Sir",
  "content":"My name is Sir Jeffrey"
 },
 {
  "id": 4,
  "title": "Prince",
  "content": "My name is Prince Gareth"
 },
 {
  "id": 5,
  "title": "Princess",
  "content": "My name is Princess Roy Roy"
},
{
 "id": 6,
 "title": "King",
 "content": "My name is King George"
}

]

My App.js:

import React from 'react';
import './App.css';
import DogsList from './components/dogslist.js';


function App() {
  return (
    <div className="App">
     <DogsList/>
    </div>
  );
}

export default App;

My List function:

import React, {Component} from 'react';
import Dog from './listlayouts.js';



 function DogList(postDetail){
  let dogs = postDetail.filteredDogs.map((dog, i) => {
    return <Dog key={postDetail.id} Name={postDetail.title} Content= 
   {postDetail.content}/>
   })
  return(
  <div>
    {dogs}
  </div>
  )
 };

 export default DogList;

List Layout:

import React, {Component} from 'react';

function Dog(postDetail){
  return(
    <div>
    <p>Name: {postDetail.title}</p>
    <p>Content: {postDetail.content}</p>
    </div>
  )
 }

export default Dog;

Search box function:

import React, {Component} from 'react';

function DogSearchBox(postDetail){
  return (
    <div>
     <input onChange={postDetail.handleInput} type ='text'/>
    </div>
  )
}

export default DogSearchBox;

And the Doglist component which should render with a empty searchbar above the list of all dogs and then the list should change once the User types in the searchbar.

import React, {Component} from 'react';
import DogList from './listfunctions.js';
import DogSearchBox from './searchboxfunctions.js';
import postData from './dogs.json';


class DogsList extends Component {
  constructor(props){
    super(props);
    this.state = {
      dogs: [
        <div>
          {postData.map((postDetail, index) => {
            return(
              <div>
               <h2>{postDetail.title}</h2>
               <p>{postDetail.content}</p>
              </div>
            )
          })}

         </div>
      ],
      searchDog:''
    }
  }

  handleInput = (e) => {
    this.setState({searchDog: e.target.value})
  }

  render() {

    let filteredDogs = this.state.dogs.filter(dog => 
    Object.values(dog).some(val => 
    val.toString().toLowerCase().includes
    (this.state.searchDog.toLowerCase())))

    return (
     <div>
      <header>
      <h1>Dogs</h1>
      </header>
      <div>
      <DogSearchBox handleInput = {this.handleInput}/>
      <DogList filteredDogs = {filteredDogs}/>
     </div>
     </div>
    );
  }
}

export default DogsList;

I am still new to it all but I have a feeling i will no longer need all of these components. I am more then happy to simplify it as much as possible. Just as long as it works as intended.

7
  • Hello when you are mapping your json data in your DogList function what is the value of the postDetail can you console log that value? Also what is the error message you get when you want to search? Commented Jul 24, 2019 at 6:30
  • "hen I type in the searchbar i get an error message. "<---what error do you get ? Commented Jul 24, 2019 at 6:38
  • TypeError: Cannot read property 'toString' of null (anonymous function) C:/Users/corey/Desktop/said1/src/components/dogslist.js:34 31 | 32 | render() { 33 | > 34 | let filteredDogs = this.state.dogs.filter(dog => Object.values(dog).some( | ^ 35 | val => val.toString().toLowerCase().includes(this.state.searchDog.toLowerCase()))) 36 | 37 | return ( Commented Jul 24, 2019 at 6:40
  • you're passing different props than what you're trying to use. <Dog Name={postDetail.title} but in Dog you are trying to use the key title rather than Name. Maybe what you want to do is <Dog postDetail={postDetail} Commented Jul 24, 2019 at 6:40
  • why is there jsx in your state? Inside DogsList you're defining state with jsx. Commented Jul 24, 2019 at 6:43

2 Answers 2

3

You're issue is you are defining JSX elements inside your state. Then you try to convert it to a string.

class DogsList extends Component {
  constructor(props){
    super(props);
    this.state = {
      dogs: [
        <div>
  // -----^--------------
          {postData.map((postDetail, index) => {
            return(
              <div>
               <h2>{postDetail.title}</h2>
               <p>{postDetail.content}</p>
              </div>
            )
          })}

         </div>
  // -------^--------------
      ],
      searchDog:''
    }
  }

instead you should just store data in state, create the elements during render

class DogsList extends Component {
  constructor(props){
    super(props);
    this.state = {
      dogs: [...postData],
      searchDog:''
    }
  }
  render() {
    const filteredDogs = ...
    return <div>
      <DogList dogs={filteredDogs} />
    </div>
  }
}

then fix the issue where you're passing the wrong props to the dog component

function DogList({dogs){
  let elems = dogs.map((dog, i) => {
    return <Dog key={dog.id} {...dog} />
  })

  return(
    <div>
      {elems}
    </div>
  )
};
Sign up to request clarification or add additional context in comments.

17 Comments

thanks John however I previously did have the data stored in state, but because I will end up wanting to have thousands of objects I think the array will just get too long and messy. (there will be many more props and images for each object). So I want to store the data as JSON as I think it will keep my code neater.
Then implement pagination, or infinite load. and probably a state management system like redux
This is not gonna fix the issue as there are incorrect props passed in the child components.
ah ok, got it :)
Well you should just conditionally render it. {hasFacebookUrl ? <Fbook /> : null }
|
2

In your list component you're passing incorrect props to the Dog component, try changing it to:

function DogList(filteredDogs){
  let dogs = filteredDogs.map((dog) => {
    return <Dog key={dog.id} dog={dog} />
   })
  return(
     <div>
      {dogs}
     </div>
     )
  };

and then in the layout component you can access the props as:

function Dog(dog){
  return(
    <div>
    <p>Name: {dog.title}</p>
    <p>Content: {dog.content}</p>
    </div>
  )
 }

EDIT: Also it seems like you're not passing correct data already in your main component. Change it to this by removing the unnecessary dogs state and passing post data directly to filter:

class DogsList extends Component {
  constructor(props){
    super(props);
    this.state = {
       searchDog:''
    }
  }

  handleInput = (e) => {
    this.setState({searchDog: e.target.value})
  }

  render() {

    let filteredDogs = postData.filter(dog => 
    Object.values(dog).some(val => 
    val.toString().toLowerCase().includes
    (this.state.searchDog.toLowerCase())))

    return (
     <div>
      <header>
      <h1>Dogs</h1>
      </header>
      <div>
      <DogSearchBox handleInput = {this.handleInput}/>
      <DogList filteredDogs = {filteredDogs}/>
     </div>
     </div>
    );
  }
}

export default DogsList;

2 Comments

thanks clarity, I am now getting this error. filteredDogs.map is not a function 6 | function DogList(filteredDogs){ > 7 | let dogs = filteredDogs.map((dog) => { 8 | return <Dog key={dog.id} dog={dog} /> 9 | }) 10 | return(
can you console.log(filteredDogs) before let dogs = filteredDogs.map((dog) => { and see what it shows?

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.