I'm working with a project written in jquery and I want to integrate this code in my react project. I'm trying to send a query to my graphql server by clicking a button.
There is a JQ function that creates multiple elements like this:
canvas.append($(`<div ><img src="${elem.artworkUrl600}" height="150px"><div ><div id="${elem.trackId}">${elem.trackName}</div><h6>by:${elem.artistName}</h6><h6>keywords:</h6><p>${elem.genres}</p><div ><button value="${elem.feedUrl}" ><a target="_blank" href="${elem.trackViewUrl}">Info link</a></i></button><div ><i id="like" ></div></div></div><hr>`)
);
My goal is to connect a function "onClick()" to all buttons inside these created elements. For that I'm trying to define a function that would query all elements by id and connect it to a function with a hook to my graphql server:
function connectFunctionalityToLike(){
$("#like").on("click", function(){ Like(this); });
}
function Like(x){
console.log("clicked");
const { loading, error, data } = useQuery(ME_QUERY);
if (loading) return 'Loading...';
if (error) return `Error! ${error.message}`;
console.log(data);
}
My function Like() does not really work because I'm missing in understanding how elements in react actually work all together with jquery. I cannot rewrite code in JQuery. I just want to integrate this existing code. Is there any way around connecting react hooks to created elements by id?
Is there
CodePudding user response:
As Andy says in his comment: "You shouldn't be mixing jQuery and React." - But, we've all be in spots where we are given no choice. If you have no choice but to use jQuery along side React, the code in the following example may be helpful.
Example is slightly different (no canvas, etc), but you should be able to see what you need.
This example goes beyond your question and anticipates the next - "How can I access and use the data from that [card, div, section, etc] that was added by jQuery?"
Here is a working StackBlitz EDIT - fixed link
Please see the comments in code:
// jQuery Addition - happens outside the React App
$('body').append(
$(`<div ><img src="${elem.artworkUrl600}" height="10px"><div ><div id="${elem.trackId}">${elem.trackName}</div><h6>by:${elem.artistName}</h6><h6>keywords:</h6><p>${elem.genres}</p><div ><button value="${elem.feedUrl}" ><a target="_blank" href="${elem.trackViewUrl}">Info link</a></i></button><div ><i id="like" ></div></div></div><hr>`)
);
export default function App() {
// state to hold the like data
const [likes, setLikes] = useState([]);
// create reference to the jquery element of importance
// This ref will reference a jQuery object in .current
const ref = useRef($('.elseTitle'));
// Like function
function Like(x) {
// ref.current is a jQuery object so use .text() method to retrieve textContent
console.log(ref.current.text(), 'hit Like function');
setLikes([...likes, ' :: ' ref.current.text()]);
}
// This is where you put
useEffect(() => {
// Add event listener and react
$('#like').on('click', function () {
Like(this);
});
// Remove event listener
return () => $('#like').off('click');
});
return (
<div>
<h1>Likes!</h1>
<p>{likes}</p>
</div>
);
}
CodePudding user response:
You should create a React component wrapper for the JQuery function.
You will have to manage the React lifecycle manually - by calling the JQuery function in a useEffect()
callback and taking care to remove the DOM elements in the cleanup:
function ReactWrapper() {
const { loading, error, data } = useQuery(ME_QUERY);
const [ data, setData ] = React.useState();
React.useEffect(() => {
jqueryFn();
$('#like').on('click', function(){ setData('from click') });
return () => {
/* code that removes the DOM elements created by jqueryFn() */
};
}, []);
if (loading) return 'Loading...';
if (error) return `Error! ${error.message}`;
return <div>{data}</div>;
}
Then, in this React component, will be allowed to use hooks.
Also, if your JQuery function is so simple, you are probably much better off with rewriting it in React.