1

I am having trouble getting the value of a select and using it to update the shelf the books are in on the server, this is the code for the booklist:

class BooksList extends Component {
render() {
const { books, onUpdate, shelf } = this.props

return(
  <ol className="books-grid">
    {books.map((book) => (
      <li key={book.id}>
       <div className="book">
         <div className="book-top">
           <div className="book-cover" style={{ width: 128, height: 192, backgroundImage: `url(${book.imageLinks.thumbnail})` }}></div>
           <div className="book-shelf-changer">
             <select onChange={onUpdate(book.id, value)} value={shelf}>
               <option value="none" disabled>Move to...</option>
               <option value="currentlyReading">Currently Reading</option>
               <option value="wantToRead">Want to Read</option>
               <option value="read">Read</option>
               <option value="none">None</option>
             </select>
           </div>
         </div>
         <div className="book-title">{book.title}</div>
         <div className="book-authors">{book.authors.join(', ')}</div>
       </div>
      </li>
    ))}
  </ol>
)

} }

Here are the server calls:

const api = "https://reactnd-books-api.udacity.com"


// Generate a unique token for storing your bookshelf data on the backend server.
let token = localStorage.token
if (!token)
  token = localStorage.token = Math.random().toString(36).substr(-8)

const headers = {
  'Accept': 'application/json',
  'Authorization': token
}

export const get = (bookId) =>
  fetch(`${api}/books/${bookId}`, { headers })
    .then(res => res.json())
    .then(data => data.book)

export const getAll = () =>
  fetch(`${api}/books`, { headers })
    .then(res => res.json())
    .then(data => data.books)

export const update = (book, shelf) =>
  fetch(`${api}/books/${book.id}`, {
    method: 'PUT',
    headers: {
      ...headers,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ shelf })
  }).then(res => res.json())

export const search = (query, maxResults) =>
  fetch(`${api}/search`, {
    method: 'POST',
    headers: {
      ...headers,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ query, maxResults })
  }).then(res => res.json())
    .then(data => data.books)

and this is the repo for the whole project:

https://github.com/Campos696/reactnd-project-myreads-starter

i have tried quite a few things, but since i'm a newbie i didn't make much progress, thanks in advance!

Daniel Campos
  • 328
  • 2
  • 16
  • I gave two different answers for fetching in React. The first one is for fetching with [only react](https://stackoverflow.com/questions/47005010/reactjs-trying-to-get-variable-from-callback/47005474#47005474) and the second one is for fetching with [redux](https://stackoverflow.com/questions/46974980/handling-loading-state-of-multiple-async-calls-in-an-action-reducer-based-applic/46980104#46980104). Tell me if you need more details. – yuantonito Oct 30 '17 at 12:25
  • I understand being new makes this question difficult to write, but the more you can provide the more help you'll receive. Are you using Redux? What library are you using for ajax requests? If you're using `isomorphic-fetch` then the above comment has a very achievable method that should answer your question. – Mark C. Oct 30 '17 at 13:40
  • i will add the server calls in the post. – Daniel Campos Oct 30 '17 at 14:29

1 Answers1

0

On your <select onChange={onUpdate(book.id, value)} value={shelf}> you are actually giving to the onChangeproperty the result of the onUpdate function.

Pass the function itself bound with the values you'll need. Another thing, where does your value parameter come from? It is not defined anywhere. I assume it's the value of the select. So you'll need to retrieve it first.

class BooksList extends Component {

    // Retrieve the value from the select, and call onUpdate whith the value, if it exists
    onSelectChange(id, event) {
        const {
            onUpdate
        } = this.props
        const { 
            value = ''
        } = this.select || {};

        if(value) {
            onUpdate(id, value);
        }
    }

    render() {
        const {
            books,
        } = this.props;

        return (
            <ol className="books-grid">
                {books.map((book) => (
                    <li key={book.id}>
                        <div className="book">
                            <div className="book-top">
                                <div className="book-cover" style={{ width: 128, height: 192, backgroundImage: `url(${book.imageLinks.thumbnail})` }}></div>
                                <div className="book-shelf-changer">


                                    <select 
                                        // See bind method: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
                                        onChange={this.onSelectChange.bind(this, book.id)}
                                        // Use refs to store references: https://reactjs.org/docs/refs-and-the-dom.html
                                        ref={(select) => {this.select = select;}}
                                    >

                                        {/* Prefer empty values */}
                                        <option value="" disabled>Move to...</option>
                                        <option value="currentlyReading">Currently Reading</option>
                                        <option value="wantToRead">Want to Read</option>
                                        <option value="read">Read</option>
                                        {/* Prefer empty values */}
                                        <option value="">None</option>
                                    </select>
                                </div>
                            </div>
                            <div className="book-title">{book.title}</div>
                            <div className="book-authors">{book.authors.join(', ')}</div>
                        </div>
                    </li>
                ))}
            </ol>
        );
    }
}
ChrisR
  • 3,922
  • 1
  • 14
  • 24
  • i have added a console.log to the onSelectChange and no matter what i click the console logs currentlyReading for value. – Daniel Campos Oct 30 '17 at 18:30
  • I had rechecked and noticed that only some books were updating the value, then i noticed it was always the last one of the bookList, should i create a component for each book to solve this problem? – Daniel Campos Oct 30 '17 at 20:39