如何通过 react-share 共享动态生成的图像?
How to share a dynamically generated image from react with react-share?
我有一个 React 应用程序,它为此使用 Plotly.js. I'd like to add image sharing functionality. I am trying to use react-share 在前端动态生成图像。社交平台需要 image URL 才能分享图片,并且不支持 base64 编码或类似编码的图片。后端已实现,因此它可以接收 base64 格式的图像,存储在数据库中,然后 return URL 到图像,然后用于与 react-share
.
共享
由于图像是动态生成的(例如,每次用户调整图表大小时它都会改变),当用户单击“共享”图标时应该完成所有操作。
所以用户点击分享图标后,前端生成的图片应该保存到后端
let imgURI;
const handleClick = () => {
Plotly.toImage('chartContainer', {
format: 'png',
width: 1000,
height: 600
})
.then(dataUrl => api.post('/image/base64ToPng', { image: dataUrl })
.then(
(response) => {
imgURI = response.data.imgURI;
},
failure => console.error(failure)
));
};
收到响应后,像这样传递给分享组件
<FacebookShareButton
url={imgURI}
>
<FacebookIcon/>
</FacebookShareButton>
代码示例不是异步的,所以图片URI没有传递给分享组件,因此分享不起作用。我试图根据是否定义使用条件传递道具,但没有提出解决方案。我还查找了处理异步 url 的 some issues in react-share repo,但似乎其中 none 处理单击时的动态图像共享。
非常感谢有关如何完成此任务的提示。
这是一个严肃的黑客领域,如果 this PR 已经完成,整个事情会简单得多。
但是,下面的代码应该可以工作(参见 codesandbox)。
关键步骤是:
- 有一些状态可以跟踪您是否有来自服务的 url。
- 当此状态为“none”时,禁用 facebook 按钮的默认行为(即
openShareDialogOnClick
= false
)
- 向异步获取 url 并设置状态(触发重新渲染)的 facebook 按钮添加
onClick
处理程序
- 使用 effect + ref 以便当 url 设置为真实的东西时,您手动调用按钮上的点击事件(现在在其
url
属性中有一个真实地址) ,然后将 url 重新设置为“none”
import { useEffect, useRef, useState } from "react";
import { FacebookIcon, FacebookShareButton } from "react-share";
async function getUrFromService(): Promise<string> {
// The real implementation would make a network call here.
await new Promise((resolve) => setTimeout(resolve, 1000));
return "https://via.placeholder.com/150";
}
export default function App() {
const shareButton = useRef<HTMLButtonElement>(null);
const [url, setUrl] = useState<string>("none"); // Unfortunately, we have to have a dummy string here, or FacebookShareButton will blow up.
// Provide an onClick handler that asyncronously fetches the url and sets it in the state.
const onClick = async () => {
// Be sure to check for the "none" state, so we don't trigger an infinite loop.
if (url === "none") {
const newUrl = await getUrFromService();
setUrl(newUrl);
}
};
// Whenever "url" changes and we re-render, we manually fire the click event on the button, and then re-set the url.
useEffect(() => {
if (url !== "none") {
shareButton.current?.click();
setUrl("none");
}
}, [url, shareButton]);
return (
<FacebookShareButton
ref={shareButton}
// Disable calling the dialog if we don't have a url yet.
openShareDialogOnClick={url !== "none"}
url={url}
onClick={onClick}
>
<FacebookIcon />
</FacebookShareButton>
);
}
尽可能使用navigator.shareapi。
有,说你可以写一个包装器来管理加载状态和禁用组件的图标。
创建异步共享组件
//AsyncShareLoader.jsx
const AsyncShareLoader = ({ url, children }) => {
const loading = !url;
return (
<div style={{ filter: `grayscale(${loading ? "100%" : "0%"}` }}>
{React.Children.map(children, (child) =>
React.cloneElement(child, {
disabled: loading,
url: loading ? "none" : url,
openShareDialogOnClick: !loading
})
)}
</div>
);
};
现在,将其用作实际反应共享图标的包装器。像这样
const Share = () => {
const [url, setUrl] = useState()
useEffect(() => {
fetch('/imgUrl').then(getUrlFromRes).then(setUrl)
}, [])
return (
<AsyncShareLoader url={url}>
<FacebookShareButton>
<FacebookIcon />
</FacebookShareButton>
</AsyncShareLoader>
);
}
扩展此技术,您可以按照 Andrew 的建议手动窃取点击
我有一个 React 应用程序,它为此使用 Plotly.js. I'd like to add image sharing functionality. I am trying to use react-share 在前端动态生成图像。社交平台需要 image URL 才能分享图片,并且不支持 base64 编码或类似编码的图片。后端已实现,因此它可以接收 base64 格式的图像,存储在数据库中,然后 return URL 到图像,然后用于与 react-share
.
由于图像是动态生成的(例如,每次用户调整图表大小时它都会改变),当用户单击“共享”图标时应该完成所有操作。
所以用户点击分享图标后,前端生成的图片应该保存到后端
let imgURI;
const handleClick = () => {
Plotly.toImage('chartContainer', {
format: 'png',
width: 1000,
height: 600
})
.then(dataUrl => api.post('/image/base64ToPng', { image: dataUrl })
.then(
(response) => {
imgURI = response.data.imgURI;
},
failure => console.error(failure)
));
};
收到响应后,像这样传递给分享组件
<FacebookShareButton
url={imgURI}
>
<FacebookIcon/>
</FacebookShareButton>
代码示例不是异步的,所以图片URI没有传递给分享组件,因此分享不起作用。我试图根据是否定义使用条件传递道具,但没有提出解决方案。我还查找了处理异步 url 的 some issues in react-share repo,但似乎其中 none 处理单击时的动态图像共享。
非常感谢有关如何完成此任务的提示。
这是一个严肃的黑客领域,如果 this PR 已经完成,整个事情会简单得多。
但是,下面的代码应该可以工作(参见 codesandbox)。
关键步骤是:
- 有一些状态可以跟踪您是否有来自服务的 url。
- 当此状态为“none”时,禁用 facebook 按钮的默认行为(即
openShareDialogOnClick
=false
) - 向异步获取 url 并设置状态(触发重新渲染)的 facebook 按钮添加
onClick
处理程序 - 使用 effect + ref 以便当 url 设置为真实的东西时,您手动调用按钮上的点击事件(现在在其
url
属性中有一个真实地址) ,然后将 url 重新设置为“none”
import { useEffect, useRef, useState } from "react";
import { FacebookIcon, FacebookShareButton } from "react-share";
async function getUrFromService(): Promise<string> {
// The real implementation would make a network call here.
await new Promise((resolve) => setTimeout(resolve, 1000));
return "https://via.placeholder.com/150";
}
export default function App() {
const shareButton = useRef<HTMLButtonElement>(null);
const [url, setUrl] = useState<string>("none"); // Unfortunately, we have to have a dummy string here, or FacebookShareButton will blow up.
// Provide an onClick handler that asyncronously fetches the url and sets it in the state.
const onClick = async () => {
// Be sure to check for the "none" state, so we don't trigger an infinite loop.
if (url === "none") {
const newUrl = await getUrFromService();
setUrl(newUrl);
}
};
// Whenever "url" changes and we re-render, we manually fire the click event on the button, and then re-set the url.
useEffect(() => {
if (url !== "none") {
shareButton.current?.click();
setUrl("none");
}
}, [url, shareButton]);
return (
<FacebookShareButton
ref={shareButton}
// Disable calling the dialog if we don't have a url yet.
openShareDialogOnClick={url !== "none"}
url={url}
onClick={onClick}
>
<FacebookIcon />
</FacebookShareButton>
);
}
尽可能使用navigator.shareapi。
有,说你可以写一个包装器来管理加载状态和禁用组件的图标。
创建异步共享组件
//AsyncShareLoader.jsx
const AsyncShareLoader = ({ url, children }) => {
const loading = !url;
return (
<div style={{ filter: `grayscale(${loading ? "100%" : "0%"}` }}>
{React.Children.map(children, (child) =>
React.cloneElement(child, {
disabled: loading,
url: loading ? "none" : url,
openShareDialogOnClick: !loading
})
)}
</div>
);
};
现在,将其用作实际反应共享图标的包装器。像这样
const Share = () => {
const [url, setUrl] = useState()
useEffect(() => {
fetch('/imgUrl').then(getUrlFromRes).then(setUrl)
}, [])
return (
<AsyncShareLoader url={url}>
<FacebookShareButton>
<FacebookIcon />
</FacebookShareButton>
</AsyncShareLoader>
);
}
扩展此技术,您可以按照 Andrew 的建议手动窃取点击