4

I am trying to build filter system. There is two filter menu. One is number of room and another is type of property. I have loaded json file from an api to space object. But when i try to pass all those spaces to SpaceFilterResults component my space array returns as [undefined, undefined].

my code for filter

class FilterSpace1 extends React.Component {
  constructor() {
    super();

    this.handleFormInput = this.handleFormInput.bind(this);

    this.state = {
      space:[],
      propertyType: 0,
      rooms: 0
    }
  }

  componentDidMount(){
        this.loadRoomFromServer();
    }

    loadRoomFromServer(){
        $.ajax({
            url:'/api/rentals/',
            dataType:'json',
            success: (data) => {
                console.log('data',data);
                this.setState({space: data.results});
                console.log('success',this.state.space);
              },
              error: (xhr, status, err) => {
                console.error(url, status, err.toString());
              }
            });
    }

  handleFormInput(propertyType, rooms) {
    this.setState({
      propertyType: propertyType,
      rooms: rooms
    })
  }

  render() {
   let space = _.map(this.state.space, (space,id) => {
    console.log('space is',space); // has an array as shown below
      <SpaceFilterResults
            key = {id}
            space={space}
            propertyType={this.state.propertyType}
            rooms={this.state.rooms}
          />
   });
   console.log('space',space); //i get space [undefined, undefined] instead of all the spaces

    return (
      <div className="filter">
        <SpaceFilterMenu
          propertyType={this.state.propertyType}
          rooms={this.state.rooms}
          onFormInput={this.handleFormInput}
        />
        {space}
      </div>
    )
  }
}

 class SpaceFilterMenu extends React.Component {
   constructor() {
     super();
     this.handleChange = this.handleChange.bind(this);
   }

   handleChange() {
     this.props.onFormInput (
       this.refs.propertyTypeInput.value,
       this.refs.roomsInput.value
     );
   }

   render() {
     return (
      <div className="container">
        <div className="row">
           <form className="filter-menu">
             <label htmlFor="roomsInput">Number of rooms</label>
              <select id="roomsInput" ref="roomsInput" onChange={this.handleChange}>
                 <option value="1">1</option>
                 <option value="2">2</option>
                 <option value="3">3</option>
                 <option value="4">4</option>
                 <option value="5">5</option>
                 <option value="6">6</option>
              </select>

             <label htmlFor="propertyTypeInput">propertyType</label>
             <select id="propertyTypeInput" ref="propertyTypeInput" onChange={this.handleChange}>
               <option value="Appartment">Appartment</option>
               <option value="House">House</option>
               <option value="Shop">Shop</option>
               <option value="Bunglow">Bunglow</option>
             </select>
           </form>
          </div>
      </div>
     );
   }
 }

class SpaceFilterResults extends React.Component {
  constructor() {
    super();
  }

  render() {
    var results = [];

   this.props.space.map((space) => {
    if(this.props.roomsInput===0){
      results.push(<Space space = {space} />);
    }
    else if (space.roomsInput === this.props.roomsInput) {
        results.push(<Space space={space} />);
      }
   });

    this.props.space.map((space) => {
      if (this.props.propertyType === 0 ) {
        results.push(<Space space={space} />);
      }
      else if (space.propertyType === this.props.propertyType) {
        results.push(<Space space={space} />);
      }
    });

    return (
      <div className="container">
        <div className="row">
          <div className="col-md-4">
             <div className="filter-results">
                <ul className="blocks blocks_3up">
                  {results}
                </ul>
              </div>
          </div>
        </div>
      </div>

    )
  }
}

class Space extends React.Component {
  constructor () {
    super();
  }

  render () {
    return (
      <li>
        <div className="feature">
          <div className="feature-hd">
            <h2 class="hdg hdg_2">{this.props.space.listingName}</h2>
          </div>
          <div className="feature-bd">
            <p>{this.props.space.room}</p>
          </div>
          <div className="feature-ft">
            <p>{this.props.space.property}% rooms</p>
          </div>
        </div>
      </li>
    )
  }
}                            

export default FilterSpace1;

my json file looks like(/api/rentals/)

enter image description here

the output of console.log('space is',space) gives space is Object {id: 1, renter: "admin", gallery: Array[2], ownerName: "tushant khatiwada", email: "[email protected]"…}

What have i done wrong? How can i pass these all space data to SpaceFilterResults component?

2
  • loadRoomFromServer should probably be a middleware, you want to keep you components as "pure" functions Commented May 6, 2016 at 14:22
  • constructor () {super();} this is useless Commented May 6, 2016 at 14:23

1 Answer 1

22

This map callback:

let space = _.map(this.state.space, (space, id) => {
  <SpaceFilterResults
        key = {id}
        space={space}
        propertyType={this.state.propertyType}
        rooms={this.state.rooms}
      />
});

will not return anything.

Here is another example that doesn’t work:

let nums = [1, 2, 3].map(x => { x * 2 })

If an arrow function body is a block, it doesn’t implicitly return anything.

// { x * 2; } is a block so this doesn’t work
let nums = [1, 2, 3].map(x => { x * 2; })

// x * 2 is an expression so this works
let nums = [1, 2, 3].map(x => x * 2)

If you use { and } inside an arrow function, you must also use a return statement:

// { x * 2 } is a block with a return so this works
let nums = [1, 2, 3].map(x => { return x * 2; })

So to fix your code, either make the arrow function body an expression by removing { and }:

let space = _.map(this.state.space, (space, id) =>
  <SpaceFilterResults
        key = {id}
        space={space}
        propertyType={this.state.propertyType}
        rooms={this.state.rooms}
      />
);

or keep it as a block but add an explicit return statement:

let space = _.map(this.state.space, (space, id) => {
  return (
    <SpaceFilterResults
        key = {id}
        space={space}
        propertyType={this.state.propertyType}
        rooms={this.state.rooms}
    />
  );
});
Sign up to request clarification or add additional context in comments.

2 Comments

why inside ajax success function this.state.space shows an array of objects but when i console on render function i get undefined ?
map() returns a new array of items that you returned from the callback. So this.state.space is your original array, and the result of _.map is a different array with undefined items because you did not return anything from the callback.

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.