I'm trying to call a vanilla javascript class inside a component.
This vanilla class is a distributor of cards and i wanted to separate the cards distribution logic from the component.
Where should I instanciate my vanilla class ?
How sure am I of the integrity of this instance (like when the components update) ?
I tried some things like putting in it inside useEffect(()=>{},[]) when the components mount but it didn't work (i didn't have access to my instance), I found this way but it works partially :
import * as WebBrowser from 'expo-web-browser';
import React, { useState, useEffect } from 'react';
import {
Image,
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
Button,
} from 'react-native';
import BasicMonoSlide from '../components/BasicMonoSlide';
import BasicMonoSlideDistributor from '../models/BasicMonoSlideDistributor';
export default function GameScreen(props) {
const [currentSlide, setCurrentSlide] = useState({});
const [joueurs,setJoueurs] = useState(
JSON.parse(JSON.stringify(props.joueurs))
);
var basicMonoSlideDistributor = new BasicMonoSlideDistributor();
useEffect(()=>{
console.log(currentSlide);
setCurrentSlide(getBasicMonoSlide());
},[]);
useEffect(()=>{
console.log(joueurs);
},[joueurs])
const nextSlide = () => {
console.log("appel next slide");
setCurrentSlide(getBasicMonoSlide());
};
const getBasicMonoSlide = ()=>{
console.log("appel getBasicMonoSlide");
var newSlideData = basicMonoSlideDistributor.getNewSlideData(joueurs,modifyJoueurs,()=>{nextSlide();});
console.log(newSlideData[2]);
return {type:'basicMonoSlide',slide:<BasicMonoSlide questionText={newSlideData[0]} btnText={newSlideData[1]} btnClickHandler={newSlideData[2]}/>};
};
const modifyJoueurs = (index,nom,sexe,orientation,enCoupleAvec,score) => {
var joueursActuel = joueurs;
console.log("modif du joueur a l'index "+index+" "+nom+","+sexe+","+orientation+","+enCoupleAvec+","+score);
const newJoueursArray = joueurs.map((item, indexMap) => {
if (indexMap === index) {
item.index=index;
item.nom=nom;
item.sexe = sexe;
item.orientation=orientation;
item.enCoupleAvec=enCoupleAvec;
item.score=score;
return item;
} else {
return item;
}
});
setJoueurs(newJoueursArray);
}
return (
<View style={styles.container}>
{currentSlide.slide||null}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
});
My "newSlideData[2]", the onPress given to my slide that has a button is an arrow function defined in my class BasicMonoSlideDistributor calling an arrow function defined in my component and when i click it works 1 or 2 times then does nothing
I know it's long, maybe just answer the first questions :)
probably the slide is attached to the DOM but you donĀ“t see this because you have problems with the CSS, check if in the element is add to the DOM (with the dev tools in your browser) and if is attached, search the problem in the CSS.
Related
I am trying to use a vanilla js library in react. since there is a lot of code, I wondered how to split it. Currently, I'm storing the code for each function in separate files... but I'm not sure how to import and run it. Is there a way to run this code in the useEffect hook or will I have to convert these old classes to es6?
editor.js
EditorUi = function (editor, container, lightbox) {
this.destroyFunctions = [];
this.editor = editor || new Editor();
this.container = container || document.body;
};
EditorUi.compactUi = true;
EditorUi.prototype.splitSize = 8;
MyComp.jsx
import React from 'react';
import EditorUi from '~/config/functions/bpm/EditorUi';
export default function MyComp() {
const divGraph = React.useRef(null);
React.useEffect(() => {
// ...?
});
return <div style={{ width: '100%', height: '80vh' }} ref={divGraph} />;
}
You've to export a function from the editor js file, then you can use it in useEffect in your component
I'm trying to scroll to an element when it comes into view. The problem is that it only works on a reload when it's already in view.
I've tried debugging it, but the ref seems to be correct and the conditionals pass. There is no return or error message so I don't know how to debug this further.
The hook works as it should so I'm really struggling to figure out what the cause is...
I need to put this in useEffect later on, but even this basic setup doesn't work. Any help is very much appreciated!
EDIT: I need to get this in the center of the screen so that I can overtake the scroll and animate the element on scroll. If I already start that functionality without it being centered, it'll stick to the bottom of the screen while it animates.
This is the component
const Component = () => {
const sectionRef = useRef<HTMLDivElement>(null);
const isOnScreen = useOnScreen(sectionRef);
if (isOnScreen && sectionRef?.current) {
sectionRef.current.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest'});
}
return (
<section ref={sectionRef}>
// ...child components
</section>
)
}
export default Component
This is the hook
import { useEffect, useState, useRef, RefObject } from 'react';
export default function useOnScreen(ref: RefObject<HTMLElement>) {
const observerRef = useRef<IntersectionObserver | null>(null);
const [isOnScreen, setIsOnScreen] = useState(false);
useEffect(() => {
observerRef.current = new IntersectionObserver(([entry]) =>
setIsOnScreen(entry.isIntersecting)
);
}, []);
useEffect(() => {
if (ref.current) {
observerRef.current?.observe(ref.current);
}
return () => {
observerRef.current?.disconnect();
};
}, [ref]);
return isOnScreen;
}
Is there a way to get basic DOM Element from React.createElement?
Like I'm trying to create a list of React audio elements for each participant in the conversation and I need to attach a track to an element, but it's not working with react elements...
My idea is something like this, but this is not working
const ref = useRef<HTMLAudioElement>()
const addAudioTrack = (track: AudioTrack) => {
const audio = React.createElement("audio", {key: track.name, ref: ref})
console.log(ref.current)
track.attach(ref.current)
setAudioTracks((prevTracks: any) => [...prevTracks, audio])
}
EDIT: reproducible example can't be totally provided because for "track" you need Twilio but here is something that you can try... I just want to know if there is a possibility to get react DOM element from ReactElement or I need to use another approach
import React, {useRef, useState} from "react";
const NewTest = () => {
const [audioTracks, setAudioTracks] = useState<any>([])
const ref = useRef<HTMLAudioElement>()
const addAudioTrack = (track: any) => {
const audio = React.createElement("audio", {key: track.name, ref: ref})
console.log(ref.current)
if(ref.current) console.log("it is working")
// track.attach(ref.current)
setAudioTracks((prevTracks: any) => [...prevTracks, audio])
}
return (
<div>
<button onClick={() => {
addAudioTrack({name: `audioTrack-${(((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)}`})
}}>
AddTrack
</button>
{audioTracks && audioTracks.map((audio: any) => {
return <div key={audio.key} style={{width: 50, height: 50, backgroundColor: "red"}}>{audio} {audio.key}</div>
})}
</div>
)
}
export default NewTest
Twilio developer evangelist here.
I think you might be thinking of this the wrong way. You do need a ref to use track.attach, but you can still handle the creation of elements via JSX.
I'd create an <AudioTrack> element that you can render with each audio track that uses useRef and useEffect to get an <audio> element and use track.attach. Something like this:
import React, { useEffect, useRef } from "react";
const AudioTrack = ({ audioTrack }) => {
const ref = useRef<HTMLAudioElement>(null);
useEffect(() => {
audioTrack.attach(ref.current);
return () => {
audioTrack.detach();
}
}, [audioTrack])
return <div><audio ref={ref}></div>;
}
export AudioTrack;
Then, in the parent container, you can render an <AudioTrack> for each of the audioTracks in your state.
I walk through how I created a Twilio Video app using React Hooks in this blog post, that might be helpful too.
I have a js file name index.js inside a folder utils
Inside the file:
export const colors = {
PRIMARY_COLOR: "#ff304f",
SECONDARY_COLOR: "#002651",
BORDER_COLOR: "#dbdbdb",
};
I try to destructuring it inside my WeatherInfo component like this:
import React from "react";
import { StyleSheet, View, Text, Image } from "react-native";
import { colors } from "../utils";
export default function WeatherInfo({ currentWeather }) {
const { PRIMARY_COLOR } = colors;
// console.log(colors);
return (
<View>
<Text style={styles.textPrimary}>{temp}</Text>
</View>
);
}
const styles = StyleSheet.create({
textPrimary: {
fontSize: 40,
color: PRIMARY_COLOR,
},
});
I got error of saying Can't find variable: PRIMARY_COLOR, however if I console.log(colors) inside the function, I can see the object printed in the expo console. However, if I do it outside the function, it works. Can someone explain to me what happened?
You are doing it right, but you just misplaced your code it should be outside from function body that's how it will be available on the whole page
const { PRIMARY_COLOR } = colors;
Move it up just one line.
I'm having a bit of difficulty implementing redux in a simple react project that I'm creating. For clarification, it's a react 360 webvr project but I've seen many similarities with react native that I'm sure this can work.
The project that I'm trying to do is simply changing the background color of a component on the click of a button. Below is my code:
constants.js
export const PICK_COLOR = 'PICK_COLOR';
actions.js
import { PICK_COLOR } from './constants'
export const pickColor = (color) => ({
type: PICK_COLOR,
payload: color
})
reducers.js
import { PICK_COLOR } from './constants';
const initialColor = {
backgroundColor: 'white'
}
export const chooseColor = (state = initialColor, action={}) => {
switch (action.type) {
case PICK_COLOR:
return Object.assign({}, state, {backgroundColor: action.payload})
default:
return state
}
}
index.js
import React from 'react';
import { createStore } from 'redux';
import { Provider, connect } from 'react-redux';
import { chooseColor } from './reducers';
import { pickColor } from './actions';
import {
AppRegistry,
StyleSheet,
Text,
View,
VrButton
} from 'react-360';
const store = createStore(chooseColor);
const mapStateToProps = state => {
return {
backgroundColor: state.chooseColor.backgroundColor
}
}
const mapDisptachToProps = (dispatch) => {
return {
onChooseColor: (event) => dispatch(pickColor(event.target.value))
}
}
class App extends React.Component {
render() {
const { backgroundColor, onChooseColor } = this.props;
return (
<Provider store={store}>
###########################################
I want this to change background color with
the click of a button.
<View style={[styles.panel, backgroundColor: this.props.backgroundColor]}>
###########################################
<VrButton style={styles.greetingBox} onClick={onChooseColor('blue')}>
<Text style={[styles.greeting, {color: 'blue'}]}>
Blue
</Text>
</VrButton>
</View>
</Provider>
);
}
};
const connectedApp = connect(mapStateToProps, mapDisptachToProps)(App);
AppRegistry.registerComponent('App', () => App);
The problem I'm having is getting over the finish line. I think I have everything set up almost correctly, but I'm unable to trigger any state change. The part where I'm getting confused is how do I connect my onClick prop handler to a state change and pass an argument? I've mixed and matched so many tutorials and videos that my head is spinning at the moment and I'm not entirely wrapping my head about setting up redux yet to troubleshoot effectively.
From what I've gathered, I don't think I have my mapDispatchToProps correctly because in the console I get the error that OnChooseColor is not a function. But how am I supposed to trigger the change? Can someone help pinpoint where I am going wrong? The help would be appreciated.
Could it be that in your mapStateToProps you are reading from state.chooseColor.backgroundColor, but it looks like your store has the shape state.backgroundColor (from what I can tell by the reducers.js)?
It's a bit late for me, so I'll probably have a look at this again tomorrow! (I'll try being more hands-on than just staring at the code!). But I'd definitively try to debug your store in your browser, by setting some breakpoints and having a look at what the store contains. There's also some handy browser extensions for react and redux that I would try out as well! (they should in theory make it easier to see what's going on with redux & react).
I can at least vouch for the react extension myself, I use it heavily just for the feature of being able to tell me which React component I'm looking at (as the DOM renders into <div> and not <MyComponent>!)
Edit: I made a small example that's very similar to this one here!
Two things I can spot by scanning your code.
1. backgroundColor is on the state in reducer.
const mapStateToProps = state => {
return {
backgroundColor: state.backgroundColor
}
}
The function for onClick should be passed instead of calling it.
onClick={() => onChooseColor('blue')}