error during drizzle useCacheCall(): TypeError: Cannot read property 'methods' of undefined
error during drizzle useCacheCall(): TypeError: Cannot read property 'methods' of undefined
我正在尝试从两个不同的地方调用 React 组件的 drizzle useCacheCall() 挂钩。这是调用的 React 组件
const FamilyContainer = ({ member }) => {
console.log("inside family container, member: ", member);
const { useCacheCall } = drizzleReactHooks.useDrizzle();
const organization = useCacheCall("MyContract", "getOrganization", member);
console.log("organization: ", organization && organization);
const maxLevel = useCacheCall("MyContract", "levels");
console.log("maxLevel: ", maxLevel && typeof maxLevel);
if (!isLoaded(organization) || !isLoaded(maxLevel)) {
return "loading...";
}
if (isEmpty(organization) || isEmpty(maxLevel)) return <PageNotFound />;
return (
<FamilySection
organization={organization}
maxLevel={parseInt(maxLevel, 10)}
/>
);
};
export default FamilyContainer;
我通过将 url 复制粘贴到浏览器地址栏来从第一个位置调用上述 React 组件:http://localhost:3000/#/invited/7434DC1BF0,执行成功。这是调用代码:
const InviteReceived = ({ playerAccount, inviterData }) => {
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
},
}));
const classes = useStyles();
const history = useHistory();
return (
<Grid container spacing={0}>
<Grid item xs={12} sm={12} md={12} lg={5}>
<Box
display="flex"
flexDirection="column"
justifyContent="center"
p={1}
m={0}
bgcolor="black"
>
<InviteReceivedSection
playerAccount={playerAccount}
inviterAccount={inviterData.ID}
/>
<PayTributeSection playerAccount={playerAccount} />
</Box>
</Grid>
<Grid item xs={12} sm={12} md={12} lg={7}>
<FamilyContainer member={inviterData.ID} />
</Grid>
</Grid>
);
};
export default InviteReceived;
从完全相同的 React 组件的第二个位置调用,通过将 url 复制粘贴到浏览器地址栏:http://localhost:3000/#/member/0x16Aa59291f0C27586B87CDcF48630cB721Dcd0cC ,不断重复失败并显示错误消息:TypeError: Cannot read 属性 'methods' of undefined。但是,如果我 运行 先调用第一个组件,然后再调用第二个组件(使用 URL),则不会发生错误(很奇怪)。
const MemberComponent = ({ playerAccount }) => {
console.log("Inside member component, playeraccount ", playerAccount);
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
},
}));
const classes = useStyles();
const history = useHistory();
return (
<Grid container spacing={0}>
<Grid item xs={12} sm={12} md={12} lg={5}>
<Box
display="flex"
flexDirection="column"
justifyContent="center"
p={1}
m={0}
bgcolor="black"
>
<ProfileDetailsSection playerAccount={playerAccount} />
<RecruitSection playerAccount={playerAccount} />
</Box>
</Grid>
<Grid item xs={12} sm={12} md={12} lg={7}>
<FamilyContainer member={playerAccount} />
</Grid>
</Grid>
);
};
export default MemberComponent;
这是错误跟踪:
TypeError: Cannot read property 'methods' of undefined
current
C:/src/hooks/create-use-cache-call.js:19
16 | {}
17 | )
18 | } else {
> 19 | const instance = drizzle.contracts[contractNameOrNames]
| ^ 20 | const cacheKey = instance.methods[methodNameOrFunction].cacheCall(...args)
21 | const cache =
22 | drizzleState.contracts[contractNameOrNames][methodNameOrFunction][
View compiled
e.useDrizzleState
C:/src/hooks/index.js:36
33 |
34 | // This is the escape hatch mentioned above. We keep a ref to `args` and whenever they change, we immediately update the state just like in the subscription.
35 | // This won't have any effect if `args` is undefined.
> 36 | const argsRef = useRef(args)
| ^ 37 | const [state, setState] = useState(
38 | mapStateRef.current(drizzle.store.getState())
39 | )
View compiled
(anonymous function)
C:/src/hooks/create-use-cache-call.js:8
5 | methodNameOrFunction,
6 | ...args
7 | ) => {
> 8 | const isFunction = typeof methodNameOrFunction === 'function'
9 | const drizzleState = useDrizzleState(drizzleState => {
10 | if (isFunction) {
11 | return contractNameOrNames.reduce(
View compiled
FamilyContainer
C:/code/MyContract/codebase/client/src/containers/FamilyContainer.js:10
7 | const FamilyContainer = ({ member }) => {
8 | console.log("inside family container, member: ", member);
9 | const { useCacheCall } = drizzleReactHooks.useDrizzle();
> 10 | const organization = useCacheCall("MyContract", "getOrganization", member);
11 | console.log("organization: ", organization && organization);
12 |
13 | const maxLevel = useCacheCall("MyContract", "levels");
View compiled
▶ 16 stack frames were collapsed.
Module../src/index.js
C:/code/MyContract/codebase/client/src/index.js:100
97 | const drizzle = new Drizzle(drizzleOptions, reduxStore);
98 | console.log("Drizzle: ", drizzle, " reduxStore: ", reduxStore);
99 |
> 100 | ReactDOM.render(
101 | <React.StrictMode>
102 | <ThemeProvider theme={theme}>
103 | <drizzleReactHooks.DrizzleProvider drizzle={drizzle}>
View compiled
__webpack_require__
C:/code/MyContract/codebase/client/webpack/bootstrap:784
781 | };
782 |
783 | // Execute the module function
> 784 | modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
| ^ 785 |
786 | // Flag the module as loaded
787 | module.l = true;
View compiled
fn
C:/code/MyContract/codebase/client/webpack/bootstrap:150
147 | );
148 | hotCurrentParents = [];
149 | }
> 150 | return __webpack_require__(request);
| ^ 151 | };
152 | var ObjectFactory = function ObjectFactory(name) {
153 | return {
View compiled
1
http://localhost:3000/static/js/main.chunk.js:7398:18
__webpack_require__
C:/code/MyContract/codebase/client/webpack/bootstrap:784
781 | };
782 |
783 | // Execute the module function
> 784 | modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
| ^ 785 |
786 | // Flag the module as loaded
787 | module.l = true;
View compiled
checkDeferredModules
C:/code/MyContract/codebase/client/webpack/bootstrap:45
42 | }
43 | if(fulfilled) {
44 | deferredModules.splice(i--, 1);
> 45 | result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
| ^ 46 | }
47 | }
48 |
View compiled
Array.webpackJsonpCallback [as push]
http://localhost:3000/static/js/bundle.js:33:19
30 | /******/ deferredModules.push.apply(deferredModules, executeModules || []);
31 | /******/
32 | /******/ // run deferred modules when all chunks ready
> 33 | /******/ return checkDeferredModules();
| ^ 34 | /******/ };
35 | /******/ function checkDeferredModules() {
36 | /******/ var result;
View source
更新:另外,我发现只有当我直接在地址栏中 post link 时才会出现问题。但如果组件是从其他组件内部遍历的,则不会发生错误。知道为什么吗?有什么想法可能只在一次调用中引起问题吗?
终于找到问题了。因为我直接使用 URL,第二次调用(一个抛出错误)甚至在 drizzle 正确初始化并设置与以太坊的连接之前就执行了 useCacheCall() 。在我的 上放置一个 组件解决了这个问题:
<drizzleReactHooks.Initializer
error="There was an error."
loadingContractsAndAccounts="loading contracts & accounts..."
loadingWeb3="loading web3..."
>
<App/>
</drizzleReactHooks.Initializer>
我正在尝试从两个不同的地方调用 React 组件的 drizzle useCacheCall() 挂钩。这是调用的 React 组件
const FamilyContainer = ({ member }) => {
console.log("inside family container, member: ", member);
const { useCacheCall } = drizzleReactHooks.useDrizzle();
const organization = useCacheCall("MyContract", "getOrganization", member);
console.log("organization: ", organization && organization);
const maxLevel = useCacheCall("MyContract", "levels");
console.log("maxLevel: ", maxLevel && typeof maxLevel);
if (!isLoaded(organization) || !isLoaded(maxLevel)) {
return "loading...";
}
if (isEmpty(organization) || isEmpty(maxLevel)) return <PageNotFound />;
return (
<FamilySection
organization={organization}
maxLevel={parseInt(maxLevel, 10)}
/>
);
};
export default FamilyContainer;
我通过将 url 复制粘贴到浏览器地址栏来从第一个位置调用上述 React 组件:http://localhost:3000/#/invited/7434DC1BF0,执行成功。这是调用代码:
const InviteReceived = ({ playerAccount, inviterData }) => {
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
},
}));
const classes = useStyles();
const history = useHistory();
return (
<Grid container spacing={0}>
<Grid item xs={12} sm={12} md={12} lg={5}>
<Box
display="flex"
flexDirection="column"
justifyContent="center"
p={1}
m={0}
bgcolor="black"
>
<InviteReceivedSection
playerAccount={playerAccount}
inviterAccount={inviterData.ID}
/>
<PayTributeSection playerAccount={playerAccount} />
</Box>
</Grid>
<Grid item xs={12} sm={12} md={12} lg={7}>
<FamilyContainer member={inviterData.ID} />
</Grid>
</Grid>
);
};
export default InviteReceived;
从完全相同的 React 组件的第二个位置调用,通过将 url 复制粘贴到浏览器地址栏:http://localhost:3000/#/member/0x16Aa59291f0C27586B87CDcF48630cB721Dcd0cC ,不断重复失败并显示错误消息:TypeError: Cannot read 属性 'methods' of undefined。但是,如果我 运行 先调用第一个组件,然后再调用第二个组件(使用 URL),则不会发生错误(很奇怪)。
const MemberComponent = ({ playerAccount }) => {
console.log("Inside member component, playeraccount ", playerAccount);
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
},
}));
const classes = useStyles();
const history = useHistory();
return (
<Grid container spacing={0}>
<Grid item xs={12} sm={12} md={12} lg={5}>
<Box
display="flex"
flexDirection="column"
justifyContent="center"
p={1}
m={0}
bgcolor="black"
>
<ProfileDetailsSection playerAccount={playerAccount} />
<RecruitSection playerAccount={playerAccount} />
</Box>
</Grid>
<Grid item xs={12} sm={12} md={12} lg={7}>
<FamilyContainer member={playerAccount} />
</Grid>
</Grid>
);
};
export default MemberComponent;
这是错误跟踪:
TypeError: Cannot read property 'methods' of undefined
current
C:/src/hooks/create-use-cache-call.js:19
16 | {}
17 | )
18 | } else {
> 19 | const instance = drizzle.contracts[contractNameOrNames]
| ^ 20 | const cacheKey = instance.methods[methodNameOrFunction].cacheCall(...args)
21 | const cache =
22 | drizzleState.contracts[contractNameOrNames][methodNameOrFunction][
View compiled
e.useDrizzleState
C:/src/hooks/index.js:36
33 |
34 | // This is the escape hatch mentioned above. We keep a ref to `args` and whenever they change, we immediately update the state just like in the subscription.
35 | // This won't have any effect if `args` is undefined.
> 36 | const argsRef = useRef(args)
| ^ 37 | const [state, setState] = useState(
38 | mapStateRef.current(drizzle.store.getState())
39 | )
View compiled
(anonymous function)
C:/src/hooks/create-use-cache-call.js:8
5 | methodNameOrFunction,
6 | ...args
7 | ) => {
> 8 | const isFunction = typeof methodNameOrFunction === 'function'
9 | const drizzleState = useDrizzleState(drizzleState => {
10 | if (isFunction) {
11 | return contractNameOrNames.reduce(
View compiled
FamilyContainer
C:/code/MyContract/codebase/client/src/containers/FamilyContainer.js:10
7 | const FamilyContainer = ({ member }) => {
8 | console.log("inside family container, member: ", member);
9 | const { useCacheCall } = drizzleReactHooks.useDrizzle();
> 10 | const organization = useCacheCall("MyContract", "getOrganization", member);
11 | console.log("organization: ", organization && organization);
12 |
13 | const maxLevel = useCacheCall("MyContract", "levels");
View compiled
▶ 16 stack frames were collapsed.
Module../src/index.js
C:/code/MyContract/codebase/client/src/index.js:100
97 | const drizzle = new Drizzle(drizzleOptions, reduxStore);
98 | console.log("Drizzle: ", drizzle, " reduxStore: ", reduxStore);
99 |
> 100 | ReactDOM.render(
101 | <React.StrictMode>
102 | <ThemeProvider theme={theme}>
103 | <drizzleReactHooks.DrizzleProvider drizzle={drizzle}>
View compiled
__webpack_require__
C:/code/MyContract/codebase/client/webpack/bootstrap:784
781 | };
782 |
783 | // Execute the module function
> 784 | modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
| ^ 785 |
786 | // Flag the module as loaded
787 | module.l = true;
View compiled
fn
C:/code/MyContract/codebase/client/webpack/bootstrap:150
147 | );
148 | hotCurrentParents = [];
149 | }
> 150 | return __webpack_require__(request);
| ^ 151 | };
152 | var ObjectFactory = function ObjectFactory(name) {
153 | return {
View compiled
1
http://localhost:3000/static/js/main.chunk.js:7398:18
__webpack_require__
C:/code/MyContract/codebase/client/webpack/bootstrap:784
781 | };
782 |
783 | // Execute the module function
> 784 | modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
| ^ 785 |
786 | // Flag the module as loaded
787 | module.l = true;
View compiled
checkDeferredModules
C:/code/MyContract/codebase/client/webpack/bootstrap:45
42 | }
43 | if(fulfilled) {
44 | deferredModules.splice(i--, 1);
> 45 | result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
| ^ 46 | }
47 | }
48 |
View compiled
Array.webpackJsonpCallback [as push]
http://localhost:3000/static/js/bundle.js:33:19
30 | /******/ deferredModules.push.apply(deferredModules, executeModules || []);
31 | /******/
32 | /******/ // run deferred modules when all chunks ready
> 33 | /******/ return checkDeferredModules();
| ^ 34 | /******/ };
35 | /******/ function checkDeferredModules() {
36 | /******/ var result;
View source
更新:另外,我发现只有当我直接在地址栏中 post link 时才会出现问题。但如果组件是从其他组件内部遍历的,则不会发生错误。知道为什么吗?有什么想法可能只在一次调用中引起问题吗?
终于找到问题了。因为我直接使用 URL,第二次调用(一个抛出错误)甚至在 drizzle 正确初始化并设置与以太坊的连接之前就执行了 useCacheCall() 。在我的
<drizzleReactHooks.Initializer
error="There was an error."
loadingContractsAndAccounts="loading contracts & accounts..."
loadingWeb3="loading web3..."
>
<App/>
</drizzleReactHooks.Initializer>