与 useEffect 异步并将数据加载到变量中
Async with useEffect and loading data into variables
我正在尝试使用 mainData
这是一个对象,由 Supabase 通过连接填充。使用 segment:SignalJourneyAudiences(segment) ,
哪个会给我:
segment: {segment: xyz}
我有这个新数组,它正在使用从连接中 return 编辑的对象,如下所示。
const unquieConstraints = [
...new Map(
mainData
.filter(row => row.segment.segment === segment.segment.segment)
.map(item => [item.constraint_value, item]),
).values(),
]
但是由于 Supabase 运行异步函数,而我 运行 它在 useEffect
我知道它无法读取。您可以在下面看到它加载为空,然后在 useEffect
调用异步函数后加载 mainData
我该如何解决这个问题,使应用程序不会因为无法读取而崩溃 segment: {segment: xxx}
我已经尝试在过滤器中使用三元运算符。但这不起作用:(
这是我的组件的主要逻辑
// CONSTRAINT CHECKBOXES
const [constraintOptions, setConstraintOptions] = useState({
constraints: [],
})
const duplicates = new Set()
const duplicateObjects = mainData.filter(
item => duplicates.size === duplicates.add(item.segment.segment).size,
)
const duplicateIds = new Set()
const nextRoundFilteredObjects = duplicateObjects.filter(
item =>
duplicateIds.size !== duplicateIds.add(item.audience_id.audience_id).size,
)
// We return only the constraint values for the unique segment
const unquieConstraints = [
...new Map(
mainData
.filter(row => row.segment === segment.segment)
.map(item => [item.constraint_value, item]),
).values(),
]
if (mainData.length === 0) {
console.warn('WARNING: mainData is empty')
} else {
console.log('mainData', mainData)
}
function handleCheckBoxes(e) {
const {value, checked} = e.target
if (checked) {
setConstraintOptions({
constraints: [...constraintOptions.constraints, value],
})
} else {
setConstraintOptions({
constraints: constraintOptions.constraints.filter(e => e !== value),
})
}
}
function openSideBar() {
setIsOpen(true)
}
function closeSideBar() {
setIsOpen(false)
}
// Handles the error / success messages popup
function popupValidation(type, message) {
if (type === 'success') {
setSuccess(true)
setSuccessMessage(message)
setTimeout(() => {
window.location.reload()
}, 2000)
} else if (type === 'warning') {
setWarning(true)
setWarningMessage(message)
setTimeout(() => {
setError(false)
window.location.reload()
}, 2500)
} else if (type === 'error') {
setError(true)
setErrorMessage(message)
setTimeout(() => {
setError(false)
window.location.reload()
}, 2500)
}
}
async function getAudienceConstratints() {
const {data, error} = await supabase
.from('SignalJourneyAudienceConstraints')
.select(
`
constraint_id,
audience_id:SignalJourneyAudiences(audience_id),
segment:SignalJourneyAudiences(segment) ,
source:SignalJourneySources(source) ,
constraint_type:SignalJourneyConstraintType(constraint_type),
constraint_value,
targeting,
frequency,
period
`,
)
.order('constraint_id', {ascending: true})
if (data) {
setMainData(data)
}
if (error) {
setErrorMessage('error', error.message)
}
}
async function addNewRelationship() {
closeSideBar()
try {
const {data, error} = await supabase
.from('SignalJourneyAudienceConstraintRelations')
.insert([
{
audience_id: segment.audience_id.audience_id,
relation: relationship.condition,
constraint_ids: constraintOptions.constraints.join('|'),
},
])
if (data) {
popupValidation('success', 'Relationship added successfully')
}
if (error) {
popupValidation('error', error.message)
}
} catch (error) {
console.error(error)
}
// RESET Relationships
setSegment('')
}
useEffect(() => {
getAudienceConstratints()
}, [])
更新
这现在可以在下面的帮助下工作了
const getAudienceConstratints = async () => {
const {data, error} = await supabase
.from('SignalJourneyAudienceConstraints')
.select(
`
constraint_id,
audience_id:SignalJourneyAudiences(audience_id),
segment:SignalJourneyAudiences(segment) ,
source:SignalJourneySources(source) ,
constraint_type:SignalJourneyConstraintType(constraint_type),
constraint_value,
targeting,
frequency,
period
`,
)
.order('constraint_id', {ascending: true})
if (error) {
setErrorMessage('error', error.message)
}
setMainData(data)
setIsLoading(false)
}
但是我对此有疑问...
const unquieConstraints = [
...new Map(
mainData
.filter(row => row.segment.segment === segment.segment.segment)
.map(item => [item.constraint_value, item]),
).values(),
]
As row.segment.segment
as as is loaded before the return of the data.
您的代码非常有道理。您的组件无法知道需要在挂载上获取的内容的值。
处理这种情况的经典方法是使用如下状态:
const MyComponent = () => {
const [isLoading, setIsLoading] = React.useState(true);
const [error, setError] = React.useState();
const [data, setData] = React.useState([]);
React.useEffect(() => {
getAudience().then((fetchedData) => {
setData(fetchedData);
setIsLoading(false);
}).catch((err) => {
setError(err.toString());
setIsLoading(false);
});
}, [])
if (!!error) return <span>Error: {error}</span>;
if (isLoading) return <span>Loading...</span>;
// Here you do stuff on your data since you know it is ready
return <span>{JSON.stringify(data, null, 2)}</span>;
}
您可以考虑创建一个可重复使用的挂钩以减少代码样板。社区为 Supabase 创建了现有的挂钩。
我正在尝试使用 mainData
这是一个对象,由 Supabase 通过连接填充。使用 segment:SignalJourneyAudiences(segment) ,
哪个会给我:
segment: {segment: xyz}
我有这个新数组,它正在使用从连接中 return 编辑的对象,如下所示。
const unquieConstraints = [
...new Map(
mainData
.filter(row => row.segment.segment === segment.segment.segment)
.map(item => [item.constraint_value, item]),
).values(),
]
但是由于 Supabase 运行异步函数,而我 运行 它在 useEffect
我知道它无法读取。您可以在下面看到它加载为空,然后在 useEffect
调用异步函数后加载 mainData
我该如何解决这个问题,使应用程序不会因为无法读取而崩溃 segment: {segment: xxx}
我已经尝试在过滤器中使用三元运算符。但这不起作用:(
这是我的组件的主要逻辑
// CONSTRAINT CHECKBOXES
const [constraintOptions, setConstraintOptions] = useState({
constraints: [],
})
const duplicates = new Set()
const duplicateObjects = mainData.filter(
item => duplicates.size === duplicates.add(item.segment.segment).size,
)
const duplicateIds = new Set()
const nextRoundFilteredObjects = duplicateObjects.filter(
item =>
duplicateIds.size !== duplicateIds.add(item.audience_id.audience_id).size,
)
// We return only the constraint values for the unique segment
const unquieConstraints = [
...new Map(
mainData
.filter(row => row.segment === segment.segment)
.map(item => [item.constraint_value, item]),
).values(),
]
if (mainData.length === 0) {
console.warn('WARNING: mainData is empty')
} else {
console.log('mainData', mainData)
}
function handleCheckBoxes(e) {
const {value, checked} = e.target
if (checked) {
setConstraintOptions({
constraints: [...constraintOptions.constraints, value],
})
} else {
setConstraintOptions({
constraints: constraintOptions.constraints.filter(e => e !== value),
})
}
}
function openSideBar() {
setIsOpen(true)
}
function closeSideBar() {
setIsOpen(false)
}
// Handles the error / success messages popup
function popupValidation(type, message) {
if (type === 'success') {
setSuccess(true)
setSuccessMessage(message)
setTimeout(() => {
window.location.reload()
}, 2000)
} else if (type === 'warning') {
setWarning(true)
setWarningMessage(message)
setTimeout(() => {
setError(false)
window.location.reload()
}, 2500)
} else if (type === 'error') {
setError(true)
setErrorMessage(message)
setTimeout(() => {
setError(false)
window.location.reload()
}, 2500)
}
}
async function getAudienceConstratints() {
const {data, error} = await supabase
.from('SignalJourneyAudienceConstraints')
.select(
`
constraint_id,
audience_id:SignalJourneyAudiences(audience_id),
segment:SignalJourneyAudiences(segment) ,
source:SignalJourneySources(source) ,
constraint_type:SignalJourneyConstraintType(constraint_type),
constraint_value,
targeting,
frequency,
period
`,
)
.order('constraint_id', {ascending: true})
if (data) {
setMainData(data)
}
if (error) {
setErrorMessage('error', error.message)
}
}
async function addNewRelationship() {
closeSideBar()
try {
const {data, error} = await supabase
.from('SignalJourneyAudienceConstraintRelations')
.insert([
{
audience_id: segment.audience_id.audience_id,
relation: relationship.condition,
constraint_ids: constraintOptions.constraints.join('|'),
},
])
if (data) {
popupValidation('success', 'Relationship added successfully')
}
if (error) {
popupValidation('error', error.message)
}
} catch (error) {
console.error(error)
}
// RESET Relationships
setSegment('')
}
useEffect(() => {
getAudienceConstratints()
}, [])
更新
这现在可以在下面的帮助下工作了
const getAudienceConstratints = async () => {
const {data, error} = await supabase
.from('SignalJourneyAudienceConstraints')
.select(
`
constraint_id,
audience_id:SignalJourneyAudiences(audience_id),
segment:SignalJourneyAudiences(segment) ,
source:SignalJourneySources(source) ,
constraint_type:SignalJourneyConstraintType(constraint_type),
constraint_value,
targeting,
frequency,
period
`,
)
.order('constraint_id', {ascending: true})
if (error) {
setErrorMessage('error', error.message)
}
setMainData(data)
setIsLoading(false)
}
但是我对此有疑问...
const unquieConstraints = [
...new Map(
mainData
.filter(row => row.segment.segment === segment.segment.segment)
.map(item => [item.constraint_value, item]),
).values(),
]
As row.segment.segment
as as is loaded before the return of the data.
您的代码非常有道理。您的组件无法知道需要在挂载上获取的内容的值。
处理这种情况的经典方法是使用如下状态:
const MyComponent = () => {
const [isLoading, setIsLoading] = React.useState(true);
const [error, setError] = React.useState();
const [data, setData] = React.useState([]);
React.useEffect(() => {
getAudience().then((fetchedData) => {
setData(fetchedData);
setIsLoading(false);
}).catch((err) => {
setError(err.toString());
setIsLoading(false);
});
}, [])
if (!!error) return <span>Error: {error}</span>;
if (isLoading) return <span>Loading...</span>;
// Here you do stuff on your data since you know it is ready
return <span>{JSON.stringify(data, null, 2)}</span>;
}
您可以考虑创建一个可重复使用的挂钩以减少代码样板。社区为 Supabase 创建了现有的挂钩。