React父组件循环渲染子组件时传递授权Fetch请求函数作为Props
Alright, let's figure out how to pass that auth fetch function (or its returned value) from your parent component to each PinnedImage child you're rendering in the loop. Here's a clear, step-by-step breakdown with code examples:
First, let's formalize that REST auth request function in your parent component. This will handle reaching out to the file server for the authorized access URL:
// Inside your parent class component fetchAuthorizedImageUrl = async (originalImageUrl) => { try { // Send your auth request to the file server's endpoint const authResponse = await fetch('/api/file-server/get-authorized-url', { method: 'POST', headers: { 'Content-Type': 'application/json', // Include any auth tokens your server requires here, e.g.: // 'Authorization': `Bearer ${this.state.userToken}` }, body: JSON.stringify({ imageUrl: originalImageUrl }) }); if (!authResponse.ok) throw new Error('Failed to get authorized URL'); const { authorizedUrl } = await authResponse.json(); return authorizedUrl; // This is the authorized URL we'll use } catch (error) { console.error('Auth request error:', error); return originalImageUrl; // Fallback to original URL if auth fails } };
You have two main options here, depending on when you need the authorized URL:
Option 1: Pass the auth function directly to the child
If you want the child component to trigger the auth request on its own (e.g., when it mounts, or when a user clicks it), just pass the function as a prop:
// Parent component's render method <div className="md-grid"> {images ? images.map((img, index) => ( <PinnedImage key={index} name={img.mediaName} originalUrl={img.downloadURL} fetchAuthorizedUrl={this.fetchAuthorizedImageUrl} // Pass the function onClick={() => this.downloadDoc(img.downloadURL)} /> )) : null} </div>
Then in your PinnedImage child component, you can call this function whenever you need:
// Inside PinnedImage component class PinnedImage extends React.Component { state = { currentImageUrl: this.props.originalUrl }; async componentDidMount() { // Fetch authorized URL when the component mounts const authorizedUrl = await this.props.fetchAuthorizedUrl(this.props.originalUrl); this.setState({ currentImageUrl: authorizedUrl }); } render() { return ( <img src={this.state.currentImageUrl} alt={this.props.name} onClick={this.props.onClick} /> ); } }
Option 2: Pre-fetch authorized URLs in the parent first
If you want to have all authorized URLs ready before rendering the children (to avoid loading states in individual kids), pre-fetch them in the parent and pass the resolved value:
// Parent component state = { images: [], authorizedUrls: {} // Store authorized URLs mapped to original URLs }; async componentDidMount() { // First, fetch your initial images list (replace with your actual data fetch) const fetchedImages = await this.fetchImagesFromApi(); this.setState({ images: fetchedImages }, async () => { // Then fetch authorized URLs for all images const authorizedUrls = {}; for (const img of this.state.images) { authorizedUrls[img.downloadURL] = await this.fetchAuthorizedImageUrl(img.downloadURL); } this.setState({ authorizedUrls }); }); } // Render with pre-fetched authorized URLs render() { const { images, authorizedUrls } = this.state; return ( <div className="md-grid"> {images.map((img, index) => ( <PinnedImage key={index} name={img.mediaName} imageSRC={authorizedUrls[img.downloadURL] || img.downloadURL} onClick={() => this.downloadDoc(img.downloadURL)} /> ))} </div> ); }
- Avoid
bindin render: Instead of usingbinddirectly in theonClickprop, use arrow functions in the render (like the example above) or define class methods as arrow functions to prevent unnecessary re-renders. - Unique
keyprop: If yourimgobjects have a unique ID (likeimg.id), use that instead ofindexfor thekeyprop—it's more reliable if the list ever reorders. - Error handling: Always include fallbacks (like returning the original URL on auth failure) to ensure your UI doesn't break if the auth request fails.
内容的提问来源于stack exchange,提问作者Owais

