Custom Sanity Action Not Updating Variables When Switching Between Documents
I can see the issue in your code! The problem is that you're using module-level variables (siteName, hookId, postUrl) that are declared outside your component. These variables are set once when the module loads and persist across component re-renders, which is why they're not updating when you switch between microsites.
Here's what's happening:
- When your component first renders for microsite "abc", it sets the module-level variables
- When you navigate to microsite "def", React may reuse the same component instance or the module is already loaded, so those
ifstatements run but the variables retain their old values or get overwritten in unexpected ways - The closure in your
formSubmitfunction captures whateverpostUrlwas at the time, not necessarily the current one
The fix: Move these variables inside your component function so they're recalculated on every render:
import React, {useState} from "react";
import {RocketIcon} from '@sanity/icons'
const baseHookUrl = "https://api.netlify.com/build_hooks/";
export function PublishMicrositeAction(props) {
const [isDialogOpen, setIsDialogOpen] = useState(false)
let micrositeId = props.id;
let siteName;
let hookId;
let postUrl;
// These now get set fresh on every render
if (micrositeId == "abc") {
siteName = "Publishing Root Site";
hookId = "123abc";
} else if (micrositeId == "def") {
siteName = "Publishing Essentials";
hookId = "456def";
} else if (micrositeId == "ghi") {
siteName = "Publishing Foundations";
hookId = "789ghi";
}
postUrl = `${baseHookUrl}${hookId}`;
console.log(micrositeId, hookId, postUrl) // Better debugging
if (props.type !== 'microsite') {
return null
}
function formSubmit(event) { // Don't forget to accept event parameter!
event.preventDefault();
var request = new XMLHttpRequest();
request.open('POST', postUrl, true);
request.onload = function() {
console.log(request.responseText);
};
request.onerror = function() {
console.error('Request failed');
};
request.send(new FormData(event.target));
setIsDialogOpen(false)
}
return {
label: "Publish Microsite",
icon: RocketIcon,
onHandle: () => setIsDialogOpen(true),
dialog: isDialogOpen && {
type: 'modal',
onClose: () => setIsDialogOpen(false),
content: <div id="modal" style={{paddingBottom: 30 + 'px'}}>
<h3>{siteName}</h3>
<p>Please enter a brief description of what was changed.</p>
<form id="publishForm" onSubmit={formSubmit}>
<label htmlFor="trigger_title">Message: </label>
<input type="text" id="trigger_title" name="trigger_title"/>
<button id="submitBtn" type="submit" style={{marginLeft: 10 + 'px'}}>Publish</button>
</form>
</div>
}
}
}Key changes:
- Moved
siteName,hookId, andpostUrlinside the component function - Changed
ifstatements toelse iffor better logic flow - Added
eventparameter toformSubmit(you were using it but not declaring it) - Changed
fortohtmlForin the label (React JSX syntax)
Even better approach - use a lookup object for cleaner code:
const MICROSITE_CONFIG = {
abc: { name: "Publishing Root Site", hookId: "123abc" },
def: { name: "Publishing Essentials", hookId: "456def" },
ghi: { name: "Publishing Foundations", hookId: "789ghi" }
};
export function PublishMicrositeAction(props) {
const [isDialogOpen, setIsDialogOpen] = useState(false)
const config = MICROSITE_CONFIG[props.id];
const postUrl = `${baseHookUrl}${config?.hookId}`;
// ... rest of your code using config.name and postUrl
}This makes it much easier to maintain and avoids the if/else chain entirely!
Show original thread2 replies
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.