简体   繁体   中英

Pass data from one component to another, via a parent

So I am new to ReacJS and JavaScript and I am stuck on an issue. I have an application, built of functional components, and what I'm trying to do is query a DB (where the schema is 2 columns, id, and content) from one component, then pass the result of that query (which happens onClick , see below) to another sibling component. What I have so far is this:

App.js:

const App = () => {
    // *Other functions and states here*

    const [content, setContent] = useState('');

    const getBookContent = useCallback(async () => {
        await fetch('/get_books/${id}')
            .then(response => 
                response.json()
            .then(data => {
                setContent(data.content)
            })
        );
    }, [setContent])

    return (
        <React.Fragment>
            <NavBar />
            <div>
                <BooksList books={books} getBooksList={getBooksList} getBookContent={getBookContent} />
                <TextEditor getBooksList={getBooksList} getBookContent={content} />
            </div>
        </React.Fragment>
    )
}

Booklist is the list of buttons.

const BooksList = ({books, getBooksList, getBookContent}) => {
    // *Other funcs*

    return (
        <React.Fragment>
            <div>{books.map(book => {
                return (
                    <div key={book.content}>
                        <button onClick={() => getBookContent()}>{book.content}</button>
                    </div>
                )
            })}</div>
        </React.Fragment>
    )

I think I am on the right sort of lines. However, I think my issue is in the parent element and getting the id for await fetch('/get_books/${id}') . I'm not sure how I should set this, or if this is even the correct thing to do.

You have to use Template literals instead of single quotes . and you have to provide the id through the function parameters. try this:

const getBookContent = useCallback(async (id) => {
    await fetch(`/get_books/${id}`)
        .then(response => 
            response.json()
        .then(data => {
            setContent(data.content)
        })
    );
}, [setContent])

And then call it in your component like this:

this.props.getBookContent(ID)

You need to use backticks:

fetch(`/get_books/${id}`)

For the id, you could do it that way:

<div key={book.id}>
  <button onClick={() => getBookContent(book.id)}>{book.content}</button>
</div>

Actually, you should use JavaScript currying and you need to read about template string . let's first fix your getBookContent function:

const getBookContent = useCallback(id => async () => {
  await fetch(`/get_books/${id}`)
    .then(response => 
      response.json()
    )
    .then(data =>
      setContent(data.content)
    )
  }, [setContent]);

The above getBookContent function is a currying function that it means after passing the id you can have a new function with the new id, the function pass another function. now pass it to the component:

~~~

<BooksList
  books={books}
  getBooksList={getBooksList}
  getBookContent={getBookContent}
/>

~~~

And inside the BookList component:

<>
  <div>
    {books.map(({ content, id }) => (
        <div key={content}>
          <button
           onClick={getBookContent(id)}
          >
            {content}
          </button>
        </div>
      )
    )}
  </div>
</>

Excuse me for changing your code style, I just make it easier to read based on Airbnb ESLint standards.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM