You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native上传后自动刷新展示组件问题求助

Hey there! Let's work through this problem together—you're right that Redux feels overkill for a small app, so let's start with lighter, more fitting solutions first, then cover a streamlined Redux guide if you still want to explore that route.

First, let's fix the obvious syntax issues in your current code that are preventing the refresh function from firing:

  1. In AddTextModal's upload method, you're referencing this.props.refreshFlatListItem but not calling it—add parentheses:
upload() {
  this.props.refreshFlatListItem(); // Call the function!
}
  1. In onSubmit, you're also not invoking this.upload—update it to this.upload();

That said, the core issue is these two components don't share a parent-child relationship, so passing props directly won't work. Here are better alternatives:


一、Lightweight Alternatives to Redux

For small apps, the simplest fix is to have your VaultScreen reload data whenever it comes into focus. This way, no matter where the upload happens, navigating back to Vault will automatically refresh the content.

Update your VaultScreen like this:

class VaultScreen extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      items: [],
      itemsFormatted: [],
      photo_id: null,
      itemSelected: '',
      searchQuery: '',
      numberOfUploads: 0
    };
    this.loadData = this.loadData.bind(this);
  }

  componentDidMount() {
    this.loadData();
    // Listen for when the screen comes into focus
    this.focusListener = this.props.navigation.addListener('focus', () => {
      this.loadData();
    });
  }

  componentWillUnmount() {
    // Clean up the listener to avoid memory leaks
    this.focusListener();
  }

  // Wrap your database fetch logic in a reusable function
  loadData() {
    db.transaction(tx => {
      tx.executeSql('SELECT * FROM items', [], (tx, results) => {
        const newItems = [];
        for (let i = 0; i < results.rows.length; i++) {
          newItems.push(results.rows.item(i));
        }
        this.setState({ items: newItems });
        // Add logic to format itemsFormatted here if needed
      });
    });
  }

  // You can keep your original refresh function if needed, but loadData does the heavy lifting now
  refreshFlatListItem = () => {
    this.loadData();
  }

  // ... rest of your component code
}

Option 2: React Context for Global Refresh Signals

If you want to trigger a refresh immediately after upload (without waiting for navigation), use React Context to create a lightweight global signal:

  1. Create a RefreshContext.js file:
import React, { createContext, useContext, useState, useCallback } from 'react';

const RefreshContext = createContext();

export function RefreshProvider({ children }) {
  const [vaultRefreshTrigger, setVaultRefreshTrigger] = useState(0);

  // Function to trigger a refresh by updating the trigger value
  const triggerVaultRefresh = useCallback(() => {
    setVaultRefreshTrigger(prev => prev + 1);
  }, []);

  return (
    <RefreshContext.Provider value={{ vaultRefreshTrigger, triggerVaultRefresh }}>
      {children}
    </RefreshContext.Provider>
  );
}

export function useRefresh() {
  return useContext(RefreshContext);
}
  1. Wrap your app in the provider in App.js:
import { RefreshProvider } from './RefreshContext';

function App() {
  return (
    <RefreshProvider>
      <NavigationContainer>
        {/* Your existing stack navigator code */}
      </NavigationContainer>
    </RefreshProvider>
  );
}
  1. Update VaultScreen to listen for the refresh trigger:
import { useRefresh } from './RefreshContext';

// Convert VaultScreen to a function component (easier to use hooks)
function VaultScreen({ navigation }) {
  const [items, setItems] = useState([]);
  const { vaultRefreshTrigger } = useRefresh();

  const loadData = () => {
    db.transaction(tx => {
      tx.executeSql('SELECT * FROM items', [], (tx, results) => {
        const newItems = [];
        for (let i = 0; i < results.rows.length; i++) {
          newItems.push(results.rows.item(i));
        }
        setItems(newItems);
      });
    });
  };

  // Reload data whenever the trigger changes
  useEffect(() => {
    loadData();
  }, [vaultRefreshTrigger]);

  // ... rest of your component logic
}
  1. Trigger the refresh in AddTextModal:
import { useRefresh } from './RefreshContext';

// For class components, use contextType
class AddTextModal extends React.Component {
  static contextType = RefreshContext;

  onSubmit = () => {
    const { textCaption } = this.state;
    if (textCaption != null) {
      this.add(textCaption);
      // Trigger the refresh
      this.context.triggerVaultRefresh();
      this.setState({ textCaption: null });
      this.props.navigation.navigate('Vault');
    }
  };

  // ... rest of your component code
}

Option 3: Event Emitter Event Bus

Create a global event emitter to send refresh signals between components:

  1. Create EventEmitter.js:
import { EventEmitter } from 'events';

const eventEmitter = new EventEmitter();
export default eventEmitter;
  1. Listen for the event in VaultScreen:
import eventEmitter from './EventEmitter';

class VaultScreen extends React.Component {
  componentDidMount() {
    this.loadData();
    // Listen for a refresh event
    this.refreshListener = eventEmitter.on('refresh-vault', () => {
      this.loadData();
    });
  }

  componentWillUnmount() {
    // Clean up the listener
    eventEmitter.removeListener('refresh-vault', this.refreshListener);
  }

  // ... loadData function and other code
}
  1. Emit the event in AddTextModal's onSubmit:
import eventEmitter from './EventEmitter';

onSubmit = () => {
  const { textCaption } = this.state;
  if (textCaption != null) {
    this.add(textCaption);
    // Send the refresh signal
    eventEmitter.emit('refresh-vault');
    this.setState({ textCaption: null });
    this.props.navigation.navigate('Vault');
  }
};

二、Streamlined Redux Guide for Your Use Case

If you eventually need to scale your app and want to use Redux, here's a minimal setup tailored to your refresh needs:

1. Install Dependencies

npm install @reduxjs/toolkit react-redux

2. Create Redux Store and Slice

Make a store.js file:

import { configureStore, createSlice } from '@reduxjs/toolkit';

// Slice to handle refresh triggers
const refreshSlice = createSlice({
  name: 'refresh',
  initialState: {
    vaultRefreshTrigger: 0
  },
  reducers: {
    triggerVaultRefresh: (state) => {
      state.vaultRefreshTrigger += 1;
    }
  }
});

export const { triggerVaultRefresh } = refreshSlice.actions;

export const store = configureStore({
  reducer: {
    refresh: refreshSlice.reducer
  }
});

3. Wrap Your App in the Redux Provider

Update App.js:

import { Provider } from 'react-redux';
import { store } from './store';

function App() {
  return (
    <Provider store={store}>
      <NavigationContainer>
        {/* Your existing stack navigator code */}
      </NavigationContainer>
    </Provider>
  );
}

4. Update VaultScreen to Listen for Redux State Changes

import { useSelector } from 'react-redux';
import { useEffect, useState } from 'react';

function VaultScreen({ navigation }) {
  const [items, setItems] = useState([]);
  const vaultRefreshTrigger = useSelector(state => state.refresh.vaultRefreshTrigger);

  const loadData = () => {
    db.transaction(tx => {
      tx.executeSql('SELECT * FROM items', [], (tx, results) => {
        const newItems = [];
        for (let i = 0; i < results.rows.length; i++) {
          newItems.push(results.rows.item(i));
        }
        setItems(newItems);
      });
    });
  };

  useEffect(() => {
    loadData();
  }, [vaultRefreshTrigger]);

  // ... rest of your component code
}

5. Dispatch the Refresh Action in AddTextModal

import { connect } from 'react-redux';
import { triggerVaultRefresh } from './store';

class AddTextModal extends React.Component {
  onSubmit = () => {
    const { textCaption } = this.state;
    if (textCaption != null) {
      this.add(textCaption);
      // Dispatch the refresh action
      this.props.triggerVaultRefresh();
      this.setState({ textCaption: null });
      this.props.navigation.navigate('Vault');
    }
  };

  // ... rest of your component code
}

// Connect the component to Redux to access the action
export default connect(null, { triggerVaultRefresh })(AddTextModal);

内容的提问来源于stack exchange,提问作者James Stirrat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 21:03:16