如何在Apollo Query组件查询后更新Store?写入数据为空问题
I see the issue you're running into—let's walk through how to fix this so your local @client query returns the data you expect after writing to the cache.
1. First: Define the processChangeRequests Field in Your Local Schema
Apollo Client needs to know the structure of your local state fields to properly cache and retrieve them. If you haven't already, add this definition to your local schema:
// Define the type for your process change request type ProcessChangeRequest { summary: String type: String created_by: String created_date: String modified_by: String modified_date: String status: String projekt: String assigned_user_overall_responsibility: String assigned_user_status_im_workflow: String planned_target_date: String description: String implicated: String live_item_id: String related_process: String to_do: String priority: String scope: String } // Add the field to your root Query type type Query { processChangeRequests: [ProcessChangeRequest] @client }
Without this, Apollo doesn't recognize the shape of your local data, so it can't properly return it when you query with @client.
2. Use cache.writeQuery Instead of client.writeData
writeData works for simple local state, but when matching the structure of a specific query (like the one in Lanes.js), cache.writeQuery is more reliable—it ensures the data you write exactly matches the query structure Apollo will use to fetch it later.
Update your Dashboard.js code like this:
<Query query={GET_ITEMS({ uid: user.uid })}> {({ loading, data: { GetProcessChangeRequests }, client }) => { if (loading) return ( <Segment> <Icon loading name='spinner' /> Loading items .... </Segment> ); // Match the exact query structure from Lanes.js client.cache.writeQuery({ query: gql` { processChangeRequests @client { summary, type, created_by, created_date, modified_by, modified_date, status, projekt, assigned_user_overall_responsibility, assigned_user_status_im_workflow, planned_target_date, description, implicated, live_item_id, related_process, to_do, priority, scope } } `, data: { processChangeRequests: [...GetProcessChangeRequests] // Spread syntax is cleaner than Object.assign here } }); return ( <Container> <div>{ ITEM_TITLE_DICTIONARY[visibilityFilter] }</div> <Divider /> <Lanes user={user} visibilityFilter={visibilityFilter} {...this.props} /> </Container> ); }} </Query>
3. Verify Your Server Data Has All Required Fields
Double-check that GetProcessChangeRequests (the data from your server query) includes every field you're trying to query in Lanes.js. If any field is missing from the server response, Apollo won't populate it in the local cache, leading to empty or incomplete results.
Add a quick log to confirm:
console.log('Server response data:', GetProcessChangeRequests);
If fields are missing, either update your server query to return them, or adjust your local schema to mark optional fields as nullable (e.g., summary: String is already nullable, only add ! if you're sure the field will always exist).
4. Avoid Repeated Cache Writes in Render
Right now, your code writes to the cache every time the component renders, which can cause unnecessary re-renders and cache inconsistencies. If Dashboard is a class component, move the fetch-and-cache logic to lifecycle methods:
class Dashboard extends React.Component { state = { loading: true }; componentDidMount() { this.updateLocalCache(); } componentDidUpdate(prevProps) { // Re-run only when user or filter changes if (prevProps.user?.uid !== this.props.user?.uid || prevProps.visibilityFilter !== this.props.visibilityFilter) { this.setState({ loading: true }); this.updateLocalCache(); } } updateLocalCache = async () => { const { user, client } = this.props; try { const { data } = await client.query({ query: GET_ITEMS({ uid: user.uid }) }); client.cache.writeQuery({ query: gql` { processChangeRequests @client { summary, type, created_by, created_date, modified_by, modified_date, status, projekt, assigned_user_overall_responsibility, assigned_user_status_im_workflow, planned_target_date, description, implicated, live_item_id, related_process, to_do, priority, scope } } `, data: { processChangeRequests: [...data.GetProcessChangeRequests] } }); this.setState({ loading: false }); } catch (err) { console.error('Failed to update cache:', err); this.setState({ loading: false }); } }; render() { const { loading } = this.state; if (loading) return ( <Segment> <Icon loading name='spinner' /> Loading items .... </Segment> ); return ( <Container> <div>{ ITEM_TITLE_DICTIONARY[this.props.visibilityFilter] }</div> <Divider /> <Lanes user={this.props.user} visibilityFilter={this.props.visibilityFilter} {...this.props} /> </Container> ); } }
5. (Simpler Alternative) Pass Data Directly as Props
If you don't need to share processChangeRequests with other components via the Apollo cache, skip the local state entirely and pass the data directly to Lanes:
// Dashboard.js <Query query={GET_ITEMS({ uid: user.uid })}> {({ loading, data: { GetProcessChangeRequests } }) => { if (loading) return ( <Segment> <Icon loading name='spinner' /> Loading items .... </Segment> ); return ( <Container> <div>{ ITEM_TITLE_DICTIONARY[visibilityFilter] }</div> <Divider /> <Lanes user={user} visibilityFilter={visibilityFilter} processChangeRequests={GetProcessChangeRequests} {...this.props} /> </Container> ); }} </Query> // Lanes.js // No need for a Query component—just use the prop const Lanes = ({ processChangeRequests }) => { return <div>{ JSON.stringify(processChangeRequests) }</div>; };
This is the most straightforward fix if you don't need the data in the global Apollo cache.
内容的提问来源于stack exchange,提问作者Edgar Moreno

