Add onScroll hook to third party reactJS components - javascript

I'm using a third party reactjs component called react-syntax-highlighter and I want to develop a logging feature that tracks users' scrolling behavior for research purposes.
However, since I'm using a third party component like this:
<div className={this.props.className}>
<SyntaxHighlighter language= {supportedLanguages.includes(this.state.language)
? this.state.language : null}
style={androidstudio} showLineNumbers={true}
lineNumberStyle={lineNumberStyle}>
{this.props.fileName ? this.state.code : 'Select a file'}
</SyntaxHighlighter>
<div className="select-language input-field">
{languageSelection}
</div>
</div>
I'm not sure how to add a hook to track the scrolling event on this component from the outside. Can someone help me take a look please? Thank you!

You can specify height for the SyntaxHighlighter component, then add overflow-y: scroll. Finally, add onScroll event listener to SyntaxHighlighter:
<SyntaxHighlighter
className={"class1"}
onScroll={() => console.log("scrolled")}
language="javascript"
>
{'code string'}
</SyntaxHighlighter>
class1 CSS:
.class1 {
height: 100px;
overflow-y: scroll;
}
Here is a working example (open console at the bottom to see the result):
https://codesandbox.io/s/jj16m0nqm5

Related

react.js image onClick not working for some reason, while same function works for another div

i am making Faq questions in react and my question div displays text when clicked on whole body as shown below:
Here is my react code. div with class "question-body" works with onclick but when I click the Plus img it has no action,any mistakes?
export default function Question({data}){
let imagid = 'img'+data.id;
function toggle(){
document.getElementById(data.id).classList.toggle('question-p') ;
document.getElementById(imagid).classList.toggle('rotateimg');
}
return(
<div className="column width100 question">
<div onClick={() => toggle()} className="question-body">
<div className="flex-between">
<label className="faq-question">{data.question}</label>
<img onClick={() => toggle()} id={imagid} className='togglequestion' src={togglequestion}></img>
</div>
<p id={data.id} className='none' dangerouslySetInnerHTML={{ __html: data.answer }}></p>
</div>
</div>
)
}
even though the answer is pretty simple here, it would require you to redo most of your code.
In order to be working with React.js effectively, you need to learn the basics (component state management,... ) - https://reactjs.org/docs/getting-started.html
I highly encourage you not to use dangerouslySetInnerHTML as it can expose your code to easy exploits.
With React.js, you don’t really want to use Document Object Model APIs (via toggle function)

Facebook event plugin in react.js disappears after click to another page link

I've been trying to get the Facebook event plugin to work in my create-react-app and can't figure it out.
In my Events.js file I added this:
<div id="fb-root"></div>
<div className="fb-page" data-href="https://www.facebook.com/[artistname]" data-tabs="events"
data-width="" data-height="" data-small-header="true" data-adapt-container-width="true"
data-hide-cover="false" data-show-facepile="true">
<div className="fb-xfbml-parse-ignore">
<blockquote cite="https://www.facebook.com/[artistname]/events">
[artistname] - coming events
</blockquote>
</div>
</div>
The SDK is imported in index.html
Everything works fine when I load the actual events page, but after clicking on "Start" and going back to "Events" the plugin disappears.
Some say to put
componentDidMount(){
window.FB.XFBML.parse()};
}
in the component, but my Event.js is a function.
I'm running out of google links now, any help is appreciated.
Easiest solution is to use the iframe option, but that doesn't directly answer your question.
Answer 1: use the useEffect hook
Example CodeSandbox here
Instead of using the componentDidMount lifecycle method from class components, you can use the useEffect hook:
useEffect(() => {
window.FB.XFBML.parse();
}, []);
This will call window.FB.XFBML.parse once per render.
Note: You may want to wrap that with an if (window.FB) to catch instances where window.FB didn't load
Answer 2: Convert to class component
You can of course convert your component to the old class based style:
export default class Events {
componentDidMount() {
window.FB.XFBML.parse();
}
render() {
return (
<>
{/* ... */}
<div
className="fb-page"
data-href={`https://www.facebook.com/${artistName}`}
data-tabs="events"
data-width=""
data-height=""
data-small-header="true"
data-adapt-container-width="true"
data-hide-cover="false"
data-show-facepile="true"
>
<div className="fb-xfbml-parse-ignore">
<blockquote cite={`https://www.facebook.com/${artistName}/events`}>
<a
href={`https://www.facebook.com/${artistName}/events`}
target="_blank"
>
{artistName} - coming events
</a>
</blockquote>
</div>
</div>
</>
);
}
}

How to set muliple class variables in riot component

I've made a header component with riot.js that should have different styling on some pages. I'd like to set the classes when mounting the tag in the html document, but can't figure out how. The tag looks like this:
<o-header>
<header class={ opts.structure, opts.overflow, opts.color }>
...
</header>
</o-header>
And here is the mounting:
riot.mount('o-header',
{
structure: 'o-header',
overflow: 's-overflow--hidden',
color: 'm-header--navy',
})
Is it a syntax error or am I misusing the opts feature here?
This is an interesting use case for options.
The format for providing multiple dynamic classes is the following,
<o-header>
<header class="{opts.structure} {opts.overflow} {opts.color}">
...
</header>
</o-header>
To take it a step further, you could apply this syntax to conditional classes,
<o-header>
<header class="{true ? opts.structure: ''} {true ? opts.color : ''}">
...
</header>
</o-header>
References:
JSFiddle: https://jsfiddle.net/31bokmyx/
RiotJS Issue: https://github.com/riot/riot/issues/2073
Conditional Dynamic Classes JSFiddle: https://jsfiddle.net/31bokmyx/19/

Styled-component not injecting all the different css for handling different props

I would like to know what can potentially cause styled-components to not inject all the neccessary css into a page's header.
I have declared a super simple button in an existing project like so:
const Button = styled.button`
background-color: ${props => props.disabled ? "red" : "blue"}
`
And used it like so:
render() {
return (
<div>
<input value={this.state.value} onChange={this.changeValue} />
<Button disabled={this.state.value === "123"}>Button</Button>
</div>
);
}
The problem is the button will display as expected on load (eg. red) but it doesn't have the blue style when the state changes.
Looking at the generated html, this is caused by the 'blue' style (.hqrbog) not injected into the header
<style type="text/css" data-styled-components="jiLefI" data-styled-components-is-local="true">
/* sc-component-id: sc-bdVaJa */
.sc-bdVaJa {}
.jiLefI{background-color:red;}
</style>
<div data-reactroot="">
<input value="12" class="drop-val">
<button class="sc-bdVaJa hqrbog">Button</button>
</div>
When I put these code in a new app created with create-react-component, everything works. But they just dont work in this existing project.
I'm wondering what can cause styled-component to not inject css insto the header properly? I'm suspecting its something to do with how the webpack or babel is set up but I don't know where to start.
Try to rename your attribute from disabled to something else.

What is an elegant way to initialize multiple react-live components from a static website?

I'm currently creating a react component library that i want to provide as an npm package. I also want to provide a documentation that features fancy live rendering of the available components on e.g. github pages.
For the live editing feature i'm planning to use react-live which provides multiple react components to display a live editor and a preview. See an example from the styled-components docs how this looks like.
The react-live component accepts a string code containing the initial code that should be displayed in the editor and a list of components scope that can be used inside the live editor.
Now i want to use gohugo or a similar static site generator to deploy my documentation. I thought i could maybe provide a <div> inside my static site that has a special class react-live-demo and i will get these containers with document.getElementsByClassName('react-live-demo'), loop over them and render the react-live component into it.
I created a code snippet that shows a little example:
const {LiveProvider, LiveEditor, LiveError, LivePreview} = window['react-live'];
// a random component that i want to render in the live editor
const MyComponent = () => (
<div>
<h1>react live demo</h1>
<p>This is a component from the script tag.</p>
</div>
);
// a wrapper for the react-live editor
const Editor = ({code, scope}) => (
<LiveProvider code={code} scope={scope}>
<div className="live-example row">
<div className="col-xs">
<LiveEditor />
<LiveError />
</div>
<div className="col-xs">
<LivePreview />
</div>
</div>
</LiveProvider>
);
// get all containers that have the initial code as innerHTML
const examples = document.querySelectorAll('script[data-name="react-live"]');
examples.forEach(example => {
// insert a new div before the script tag
const container = document.createElement('div');
example.parentNode.insertBefore(container, example.nextSibling);
// render the editor with the code from the script tag
const code = example.innerHTML.trim();
ReactDOM.render(<Editor code={code} scope={{MyComponent}} />, container);
});
.static-content {
background-color: papayawhip;
}
.live-example {
border: 1px solid orange;
}
.react-live-demo.code {
display: none;
}
.invalid {
color: red;
}
<p class="static-content">HERE IS SOME STATIC HTML CONTENT</p>
<script type="text/html" data-name="react-live">
<div>
<h1>react live demo</h1>
<p>This code is editable.</p>
</div>
</script>
<p class="static-content">SOME MORE STATIC HTML CONTENT</p>
<script type="text/html" data-name="react-live">
<MyComponent />
</script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/flexboxgrid/6.3.1/flexboxgrid.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://unpkg.com/react-live#1.7.0/dist/react-live.min.js"></script>
The question is now:
How do embed the code string into my static site so that i can grab it with my js code and pass it to my react-live component?
I thought about <pre> or something like that. Or should i just embed it as inner html and read that? But then it would be displayed for short when the react component hasn't rendered yet. Or should i use some sort of script tag and make it available as globals? The key goal is to make it as easy as possible to add live editing examples to the documentation without touching any javascript code.
However if i pass something like <MyComponent /> as innerHTML this does of course not work as you can see in the code snippet.
Any best practice for that use case appreciated.
EDIT:
Based on the suggestion of #Daniel Alexandrov i edited the code snippet. The solution now reads the innerHTML of script tags with type="text/html set and creates a <div> container to insert the editor. This seems to work quite well. Any more ideas?
In my opinion the best choice is to use the <script> tag with a custom type attribute. Take a look at the Knockout.js template binding which uses type="text/html or the Angular <script type="text/ng-template">
This way the browser will ignore the script tag completely, because it doesn't know how to interpret it.

Categories

Resources