Getting html element attribute is unreliable - html

So i am trying to get a data attribute of a div element but it is giving a null but not always; after like ten times of showing a null, it shows the attribute so what am i missing? is it a bug?
import { useEffect, useState } from 'react';
import './App.css';
function App() {
const [toggleComments, setToggleComments] = useState(false);
const changetoggleState = (e)=> { setToggleComments(toggleComments ? false : true);
console.log(toggleComments); console.log(e.target.getAttribute('data-comment-data'))};
return <div data-comment-data="hello there" onClick={changetoggleState}>Hello World</div>
};
export default App;

Change your code to:
e.target.getAttribute("data-comment-data")
Online demo:
https://codesandbox.io/s/spring-paper-dsd1tt?file=/src/App.js:305-347

So the problem was i put the data attribute on the div but when i was clicking for some reason i was clicking on a PNG icon inside the div that did not have any data attribute. that is why it sometimes worked when i did not click on the PNG.

Related

Custom Styled Input field in react js

I am looking for input field which take the input in formated way based on user selection of font, bullets and code type.
Provided the image below
Code should be in React Js and output can be html in json format
You're trying to say you need to implement a rich text editor using React?
Well, in that case I personally use jodit-react because it's open-source, works well with TypeScript and NextJS and outputs the text in HTML format. You can find the project here and basic implementation looks like this.
import React, {useState, useRef, useMemo} from 'react';
import JoditEditor from "jodit-react";
const Example = ({placeholder}) => {
const editor = useRef(null)
const [content, setContent] = useState('')
const config = useMemo({
readonly: false // all options from https://xdsoft.net/jodit/doc/,
placeholder: placeholder || 'Start typing...'
},
[placeholder])
return (
<JoditEditor
ref={editor}
value={content}
config={config}
tabIndex={1} // tabIndex of textarea
onBlur={newContent => setContent(newContent)} // preferred to use only this option to update the content for performance reasons
onChange={newContent => {}}
/>
);
}
Take a look at this example below.
Hope this helps!
Cheers!

In React application, Images cannot show when an image url is string property of a object

I cannot show the image when the image url is string property in a object.
For example:
import React, {Fragment, useState} from 'react';
const profile = (props) => {
const [user, setUser] = useState(null);
useEffect(() => {
setUser({
name: 'John',
photo: './asset/images/user.png'
})
}, [])
return (
<Fragment>
<img src={user.photo} alt="photo" />
<p>{user.name}</p>
</Fragment>
)
}
Of course I can solve this by importing image object like import img from './assets/images/user.png'. But I need to know how to show image without importing it.
Does anyone solve the problem?
You can see one example working here: https://codesandbox.io/s/relaxed-sinoussi-ikown?file=/src/App.js
The main problem is you're trying to access the image as a relative route from your component.
But, when you want to do something like that your component can be anywhere in the application. So, the way to do it is:
Include your images in public/
Access your images using the absolute route from /public

React - is the following true about how html tags' attribute values change when a component is reexecuted?

Can I verify my observation (based on the code below)?:
Class values of an element added in the html markup of a component don't neccessarily 'persist' - when the component is re-executed (perhaps as the result of a change in state), the class value from the last execution can disappear.
However, class values written via vanilla JS persist.
I'm always looking for best practices in code to avoid problems down the line. Is this code a reasonable way to add a class to a tag in React?
sandbox: https://codesandbox.io/s/purple-moon-epmmu?file=/src/styles.css:59-126
import "./styles.css";
import React, { useState, useEffect } from "react";
export default function App() {
let [color, setColor] = useState(false);
function updateColor() {
if (color) {
setColor("");
} else {
setColor("red");
}
}
useEffect(() => {
document.querySelector(`div`).classList.add(`green-text`);
}, []);
return (
<>
<div className={color ? "red" : null} onClick={updateColor}>
Click to add/remove red class
</div>
</>
);
}
.red {
background-color: red;
}
.green-text {
color: green;
}
I would highly recommend you to try out the classnames library to inject class attribute value dynamically. It's a very elegant library which helps avoid complicated code pertaining to css updates, when the codebase gets bigger.
I have tweaked your example, including some naming changes, removing unwanted code and added classnames. Also you can pass in any other class names from other components as such, and render it dynamically too. This is how you'd do it:
import "./styles.css";
import React, { useState, useEffect } from "react";
import classnames from "classnames"
export default function App(props) {
const [hasRed, setHasRed] = useState(false);
return (
<div className={classnames(
["green-text", props.otherClassNamesIfAny],
{
"red": hasRed,
}
)}
onClick={setHasRed(!hasRed)}
>
Click to add/remove red class
</div>
);
};

How to render component by adding the component using innerHTML?

I have a component A which only contain a div with an id and a buttons that renders a component inside the div using innterHTML document.getElementById('my-router-outlet').innerHTML = '<app-component-b-page></app-component-b-page>';. But this is not rendering I wonder why?.
I'm trying to avoid using ngIf to be a selector for which component should be rendered for performance reason. Also if I clear the innerHTML does the resources of that component will be cleared?
Okay so a few things here
innerHTML = '<app-component-b-page></app-component-b-page>' is never going to work, angular wont recognise the angular component tag from a innerHTML call
using *ngIf wont affect the performance of the page, so doing the following
<app-component-b-page *ngIf="value === true"></app-component-b-page>
is probably you best option here
If you really don't want to use *ngIf you can use #ViewChild and ComponentFactoryResolver
In your HTML
<!-- this is where your component will be rendered -->
<div #entry></div>
In your component
import { Component, OnInit, ViewChild, ViewContainerRef, ComponentFactoryResolver } from '#angular/core'
import { YourComponent } from ... // import the component you want to inject
// ...
export class ...
#ViewChild('entry', {read: ViewContainerRef, static: true }) entry: ViewContainerRef;
constructor(
private _resolver: ComponentFactoryResolver
) {}
showComponent() {
const factory = this._resolver.resolveComponentFactory(YourComponent);
// this will insert your component onto the page
const component = this.entry.createComponent(factory);
}
// and if you want to dynamically remove the created component you can do this
removeComponent() {
this.entry.clear();
}
You are adding the element to the dom directly and it's not rendered by Angular.
You should go for the *ngIf.

How to navigate in React-Native?

I am using ReactNavigation library in my react-native project and since 6 hours I am trying to navigate from one screen to others screen and have tried every possible way but I think I am not able to get the logic properly.
This is my project structure.
Here
The way I am doing it.
const AppStack = StackNavigator({ Main: Feeds });
const AuthStack = StackNavigator({ Launch: LaunchScreen, });
export default SwitchNavigator({
Auth: AuthStack,
App: AppStack
});
In my LaunchScreen.js
const SimpleTabs = TabNavigator(
{
Login: {
screen: Login,
path: ""
},
SignUp: {
screen: SignUp,
path: "doctor"
}
},
);
<SimpleTabs screenProps={{rootNavigation : this.props.navigation }}/>
But the problem is in my LaunchScreen Component there is a TabNavigator which contains my other two components Login.js and SignUp.js but the button in my Login.js doesn't navigate it to Feed.js.
When you click on the button this is performed.
signInAsync = async () => {
await AsyncStorage.setItem('userToken', 'abc');
this.props.navigation.navigate('Main');
console.log("AAAAAsSSS");
};
My LaunchScreen.js contains a TabNavigation which lets you slide between two components ie. Login.js and SignUp.js.
Now when you click on the Login button which is in Login.js component it will authenticate the user and will switch the entire LauchScreen.js component with the Feed.js component.
I am a noob to react-native.
You can use react-native-router-flux (npm install --save react-native-router-flux)
just make one Navigator.js file and define each page you wanted to navigate.
import React from 'react';
import { Router, Scene } from 'react-native-router-flux';
import LaunchScreen from '../components/LaunchScreen.js';
import Feed from '../components/Feed.js';
const Navigator = () => {
return (
<Router>
<Scene key="root">
<Scene key="lauchscreen" component={LaunchScreen} hideNavBar initial />
<Scene key="feedscreen" type="reset" hideNavBar component={Feed} />
</Scene>
</Router>
);
};
export default Navigator;
now in your App.js file add this:
import Navigator from './src/Navigator.js';
export default class App extends Component<Props> {
render() {
return (
<Navigator />
);
}
}
now in your login.js when you click on login button write this:
import { Actions } from 'react-native-router-flux';
onLoginClick() {
Actions.feedscreen();
}
Thats it.. happy coding.
If you want to navigate to Feeds.js then navigate as
this.props.navigation.navigate('App');
not as
this.props.navigation.navigate('Main');
because your
export default SwitchNavigator({
Auth: AuthStack,
App: AppStack // here is your stack of Main
});
refer example
I came across the same issue few months ago. Thank god you have spent just 6 hours, i almost spent around 4 days in finding a solution for it.
Coming to the issue, Please note that in react-navigation you can either navigate to siblings or children classes.
So here, You have a swtichNavigator which contain 2 stack navigators (say stack 1 and stack 2), stack1 has feeds and stack2 has a tab navigator with login and signup.
Now you want to navigate from login.js to feeds.js(say file name is feeds.js). As mentioned already you can not navigate back to parent or grandparent. Then how to solve this issue?
In react native you have the privilege to pass params (screenprops) from parent to children. Using this, you need to store this.props.navigation of launchScreen into a variable and pass it to tab/login (check the tree structure). Now in the login.js use this variable to navigate.
You are simply passing the navigating privilege from parent to children.
Editing here:
<InnerTab screenProps={{rootNavigation : this.props.navigation }} />
Here, InnerTab is the tab navigator.
export const InnerTab = TabNavigator({
login: {
screen: login,
},
},
signup: {
screen: signup,
},
},
},
in login class, use const { navigate } = this.props.screenProps.rootNavigation;
Now you can use variable navigate.
I know its little tricky to understand but i have tried and it works.
Write your Navigator.js file as below,
import React from 'react'
import { NavigationContainer, useNavigation } from '#react-navigation/native'
import { createStackNavigator } from '#react-navigation/stack'
const SwitchNavigatorStack = () => {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName='{nameofscreen}' screenOptions={screenOptions}>
<Stack.Screen name='{nameofscreen}' component={{nameofscreen}}/>
<Stack.Screen name='{nameofscreen}' component={{nameofscreen}}/>
<Stack.Screen name='{nameofscreen}' component={{nameofscreen}}/>
<Stack.Screen name='{nameofscreen}' component={{nameofscreen}}/>
</Stack.Navigator>
</NavigationContainer>
)
}
export default SwitchNavigatorStack
Once, you are done with that change your App.js file to,
import SignedInStack from './navigation'
import React from 'react'
export default function App() {
return <SwitchNavigatorStack/>
}
After this, you are done with setting your project for navigating. In all the components where you want to add navigation feature make sure you use the navigation.navigate() (or) navigation.push() method. Also make sure you hook navigation constant by import useNavigation library. For example,
const Login = () => {
const navigation = useNavigation()
< Button title = 'Login' onPress={() => navigation.navigate('{nameofscreen}')} />
}
with this code snippet you can implement navigation between screens using #react-navigation/native and #react-navigation/stack