将子项用作函数时组件不呈现
Component not rendering when using children as function
我正在使用 react-apollo
查询 graphQL 服务器,并能够成功地为客户端提供数据。由于会有多个地方,我将查询数据我正在尝试创建一个容器(重构)来封装 useQuery
挂钩,以便它可以在一个地方使用。
第一次尝试(按预期工作)
const HomeContainer = () => {
const { data, error, loading } = useQuery(GET_DATA_QUERY, {
variables: DATA_VARIABLES
});
const [transformedData, setTransformedData] = useState();
useEffect(() => {
if(!!data) {
const transformedData = someTransformationFunc(data);
setTransformedData(...{transformedData});
}
}, [data]);
if (loading) {
return <div>Loading data ...</div>;
}
if (error) {
return <p>Error loading data</p>;
}
if (!data) {
return <p>Not found</p>;
}
return <Home transformedData={transformedData} />;
};
我想将围绕查询的不同阶段的仪式封装到一个新的容器中(加载、错误状态),这样我就可以减少代码重复。
第一次尝试重构
- 查询容器在
query
、variables
和 callback
中传递。这负责根据查询状态(加载、错误或无数据返回时)返回不同的节点。
const HomeContainer = () => {
const {data, error, loading} = useQuery(GET_DATA_QUERY, {
variables: DATA_VARIABLES
});
const [transformedData, setTransformedData] = useState();
const callback = (data) => {
const transformedData = someTransformationFunc(data);
setTransformedData(...{
transformedData
});
};
return (
<QueryContainer
query={GET_DATA_QUERY}
variables={DATA_VARIABLES}
callback ={callback}
>
<Home transformedData={transformedData} />
</QueryContainer>
)
};
const QueryContainer = ({callback, query, variables, children }) => {
const {data, error, loading } = useQuery(query, {
variables: variables
});
// Once data is updated invoke the callback
// The transformation of the raw data is handled by the child
useEffect(() => {
if (!!data) {
callback(data);
}
}, [data]);
if (loading) {
return <div > Loading data... < /div>;
}
if (error) {
return <p > Error loading data < /p>;
}
if (!data) {
return <p > Not found < /p>;
}
return children;
};
QueryContainer
正在使用 useEffect
并在 data
返回时调用 callback
。我觉得这有点混乱,违背了封装在父级中并使用 callback
与子级交谈和更新的目的。
第三次尝试(使用 children 作为函数)
摆脱了回调并将数据作为第一个参数传递给 children
函数。
const HomeContainer = () => {
return (
<QueryContainer
query={GET_DATA_QUERY}
variables={DATA_VARIABLES}
>
{(data) => {
const transformedData = someTransformationFunc(data);
return <Home transformedData={transformedData} />;
}}
</QueryContainer>
)
};
const QueryContainer = ({ query, variables, children }) => {
const { data, error, loading } = useQuery(query, {
variables: variables
});
if (loading) {
return <div>Loading data ...</div>;
}
if (error) {
return <p>Error loading data</p>;
}
if (!data) {
return <p>Not found</p>;
}
return children(data);
};
我希望它能正常工作,因为没有任何真正改变,并且当 data
更新时新渲染将子项作为函数调用,并以 data
作为参数。
但是当我导航到那条路线时,我看到一个黑屏(没有错误,我可以看到正确的数据记录到控制台中)
如果我再次单击 link,我可以看到提交给 DOM 的组件。
不太确定这里发生了什么,想知道是否有人可以阐明这里发生的事情。
嗯,应该可以……
尝试这样的事情(组件注入,有点像 HOC - inspiration):
const HomeContainer = () => {
return (
<QueryContainer
query={GET_DATA_QUERY}
variables={DATA_VARIABLES}
transformation={someTransformationFunc}
renderedComponent={Home}
/>
)
};
const QueryContainer = ({ query, variables, transformation, renderedComponent: View }) => {
const { data, error, loading } = useQuery(query, { variables });
if (loading) {
return <div>Loading data ...</div>;
}
if (error) {
return <p>Error loading data</p>;
}
if (!data) {
return <p>Not found</p>;
}
// let transformedData = transformation(data);
// return <View transformedData={transformedData} />;
return <View transformedData={transformation ? transformation(data) : data} />;
};
如果仍然不起作用(!?),将 data
和 transformation
作为 props 传递并使用它们来初始化状态(使用 useState
或 useEffect
)。
你 really/still 需要 <HomeContainer/>
作为抽象吗? ;)
我在上面添加的代码片段在隔离状态下按预期工作。
https://codesandbox.io/s/weathered-currying-4ohh3
问题出在层次结构树下的某些其他组件导致组件无法重新呈现。
第二个实现按预期工作,因为组件再次呈现为从父级调用的回调无效。
我正在使用 react-apollo
查询 graphQL 服务器,并能够成功地为客户端提供数据。由于会有多个地方,我将查询数据我正在尝试创建一个容器(重构)来封装 useQuery
挂钩,以便它可以在一个地方使用。
第一次尝试(按预期工作)
const HomeContainer = () => {
const { data, error, loading } = useQuery(GET_DATA_QUERY, {
variables: DATA_VARIABLES
});
const [transformedData, setTransformedData] = useState();
useEffect(() => {
if(!!data) {
const transformedData = someTransformationFunc(data);
setTransformedData(...{transformedData});
}
}, [data]);
if (loading) {
return <div>Loading data ...</div>;
}
if (error) {
return <p>Error loading data</p>;
}
if (!data) {
return <p>Not found</p>;
}
return <Home transformedData={transformedData} />;
};
我想将围绕查询的不同阶段的仪式封装到一个新的容器中(加载、错误状态),这样我就可以减少代码重复。
第一次尝试重构
- 查询容器在
query
、variables
和callback
中传递。这负责根据查询状态(加载、错误或无数据返回时)返回不同的节点。
const HomeContainer = () => {
const {data, error, loading} = useQuery(GET_DATA_QUERY, {
variables: DATA_VARIABLES
});
const [transformedData, setTransformedData] = useState();
const callback = (data) => {
const transformedData = someTransformationFunc(data);
setTransformedData(...{
transformedData
});
};
return (
<QueryContainer
query={GET_DATA_QUERY}
variables={DATA_VARIABLES}
callback ={callback}
>
<Home transformedData={transformedData} />
</QueryContainer>
)
};
const QueryContainer = ({callback, query, variables, children }) => {
const {data, error, loading } = useQuery(query, {
variables: variables
});
// Once data is updated invoke the callback
// The transformation of the raw data is handled by the child
useEffect(() => {
if (!!data) {
callback(data);
}
}, [data]);
if (loading) {
return <div > Loading data... < /div>;
}
if (error) {
return <p > Error loading data < /p>;
}
if (!data) {
return <p > Not found < /p>;
}
return children;
};
QueryContainer
正在使用 useEffect
并在 data
返回时调用 callback
。我觉得这有点混乱,违背了封装在父级中并使用 callback
与子级交谈和更新的目的。
第三次尝试(使用 children 作为函数)
摆脱了回调并将数据作为第一个参数传递给 children
函数。
const HomeContainer = () => {
return (
<QueryContainer
query={GET_DATA_QUERY}
variables={DATA_VARIABLES}
>
{(data) => {
const transformedData = someTransformationFunc(data);
return <Home transformedData={transformedData} />;
}}
</QueryContainer>
)
};
const QueryContainer = ({ query, variables, children }) => {
const { data, error, loading } = useQuery(query, {
variables: variables
});
if (loading) {
return <div>Loading data ...</div>;
}
if (error) {
return <p>Error loading data</p>;
}
if (!data) {
return <p>Not found</p>;
}
return children(data);
};
我希望它能正常工作,因为没有任何真正改变,并且当 data
更新时新渲染将子项作为函数调用,并以 data
作为参数。
但是当我导航到那条路线时,我看到一个黑屏(没有错误,我可以看到正确的数据记录到控制台中)
如果我再次单击 link,我可以看到提交给 DOM 的组件。
不太确定这里发生了什么,想知道是否有人可以阐明这里发生的事情。
嗯,应该可以……
尝试这样的事情(组件注入,有点像 HOC - inspiration):
const HomeContainer = () => {
return (
<QueryContainer
query={GET_DATA_QUERY}
variables={DATA_VARIABLES}
transformation={someTransformationFunc}
renderedComponent={Home}
/>
)
};
const QueryContainer = ({ query, variables, transformation, renderedComponent: View }) => {
const { data, error, loading } = useQuery(query, { variables });
if (loading) {
return <div>Loading data ...</div>;
}
if (error) {
return <p>Error loading data</p>;
}
if (!data) {
return <p>Not found</p>;
}
// let transformedData = transformation(data);
// return <View transformedData={transformedData} />;
return <View transformedData={transformation ? transformation(data) : data} />;
};
如果仍然不起作用(!?),将 data
和 transformation
作为 props 传递并使用它们来初始化状态(使用 useState
或 useEffect
)。
你 really/still 需要 <HomeContainer/>
作为抽象吗? ;)
我在上面添加的代码片段在隔离状态下按预期工作。
https://codesandbox.io/s/weathered-currying-4ohh3
问题出在层次结构树下的某些其他组件导致组件无法重新呈现。
第二个实现按预期工作,因为组件再次呈现为从父级调用的回调无效。