Use imported variable as a dinamic prop in React - javascript

Sorry for the noob question, but I'm a noob in React and I am strugling with this.
I have a file that exports a variable that is being mutated over time. Let's say something like this (not the real code, the variable is changing correctly):
// variable.js
let myVar = 0;
setInterval(() => myVar++, 3000);
export { myVar };
and a react component that has to display the current value:
import React, { Component, Fragment } from "react";
import { myVar } from './variable.js';
export default class myComponent extends Component {
constructor(props) {
super(props);
}
render() {
return (
<Fragment>
<div>{myVar}</div>
</Fragment>
);
}
}
What would be the best approach to get the variable displayed correctly while they change? I have tryied to set is as a state, as a prop and rendering it directly, but I am missing something.
I can not export a getter function, as I don't know from the component when the variable is going to change, but maybe I can change the approach? maybe throwing an event in each change?

Try this, It won't work like the real-time update. But you can access like below
You can create a custom hook, that will update real-time
export default function useUpdate() {
const [myVar, setState] = useState(0)
setTimeout(function () {
setState(myVar++);
}, 3000);
return [myVar, setState];
}
import React, { Component, Fragment } from "react";
import { useUpdate } from './variable.js';
export default () => {
const [myVar] = useUpdate();
return (
<Fragment>
<div>{myVar}</div>
</Fragment>
);
}

Related

Forcefully update the component on updated value inside the render method react native

I am trying to forcefully rerender the complete component on value change inside the render function.
Below is a sample code to explain my problem. Profile component I am calling after the login and it's called and two functions inside this getting called and the value is set in the state. Now I am on another screen where I am updating mssidnNumber inside the context and that change I can see in the Profile render() function val. let val = this.context.mssidnNumber; and this val value will change on condition so on this basis I am trying to rerender the complete Profile component again so all values will update. How can I do this please help? Is that possible?
import React, { Component } from 'react';
import { View} from 'react-native';
class Profile extends Component {
constructor(props) {
super(props);
}
async componentDidMount() {
this.Profilefunction();
}
Profilefunction = () =>{
this.setState({})
await this.profile2fucntion();
}
profile2fucntion =() => {
}
render() {
let val = this.context.mssidnNumber;
return (
<View>
</View>
);
}
}
export default Profile;

how to setstate in if react native

Hello I'm trying to export exportTest to another js file and do re-render. I'm trying it like this
import React, { useState } from 'react';
import { StyleSheet, View } from 'react-native';
var n;
export var exportTest;
function foo()
{
//doing something and giving back n as 1 or 0
}
export default function App () {
const [test,setTest] = useState();
if(n == 0)
{
//doing something
setTest('n is zero')
}
else
{
//doing something
setTest('n is not zero')
}
exportTest=test
return(
<View>
...
...
...
</View>
);
}
I'm getting error too meny re-renders, because I'm doing setTest in if
How can I do setTest once in last line of if? n is changing in some function, I'm getting it as 1 or 0.
And this is how I'm importing exportTest in another file import {exportTest} from './App.js';
import React, { useState } from 'react';
import { StyleSheet, TouchableOpacity, View, Text } from 'react-native';
export const exportTest = () => {
const [test,setTest] = useState();
let n = 0;
if(n == 0)
{
setTest('n is zero')
}
else
{
setTest('n is not zero')
}
exportTest=test
return(
...
...
...
);
}
Try that. You are importing it as a const hence the {exportTest} import you wrote. You need to export exportTest as a const.
There are a lot of things wrong and you deleted the return so your purpose isn't clear. See if that helps. Feel free to comment again. I recommend cleaning up your code.
You're creating an infinite loop. State and prop changes trigger re-render, and in your case - the re-render triggers a state update. That's why state updates should NEVER be a part of your renderer's logic.
From reactjs.org:
What does setState do?
setState() schedules an update to a component’s state object. When
state changes, the component responds by re-rendering
Normally, you would do all your state manipulations on componentDidMount or componentWillReceiveProps, and hook's alternative to those is an Effect Hook.
useEffect(() => {
// componentWillMount
return () => {
// componentWillUnmount
};
});
Trigger on props updates:
useEffect(() => {
// prop abc changed
}, [props.abc]);
Notice, in the latter example I left out the return statement.
https://reactjs.org/docs/hooks-effect.html

call react component-element as variable

Is it possible to call a React component element with a variable inside?
import React from "react"
/*React functional component*/
function someName() {
const someVar = "componentName"; //the name of the called component
return(
<{someVar}/>
)
}
export default someName;
I try to implement this in a router and to change the filenames(Sites) (in the element) dynamically with useState from fetched data.
I am open to all kind of help :)
There is no direct way to do that but you can use this approach.
import ComponentA from '...path';
import ComponentB from '...path';
...
const components = {
componentA: ComponentA,
componentB: ComponentB,
...
}
...
function App(props) {
const TargetComponent = components[props.componentName];
return <TargetComponent />;
}

How to Programmatically Provide and Consume Context?

So my question is a simple one. In React js I want to pass some states and handlers from a parent to its 3rd grandchild using Context. I have implemented this within the jsx but I want to use the states within the javascript o that I have some logic before I completely output my states.
I have divided my question into 2 parts. 1.) What I have done so far. 2.) What I want to do essentially.
1.)
// this file just stores the Context
MyContext.js
import React, { Component } from 'react';
export const MyContext = React.createContext();
MyProvider.js // this class is used by the parent and the child to have access to the provider
import React, { Component } from 'react';
import {MyContext} from '../MyContext'
class MyProvider extends Component {
state = {
name: 'Wes',
age: 100,
cool: true
}
render() {
return (
<MyContext.Provider value={{
state: this.state,
growAYearOlder: () => this.setState({
age: this.state.age + 1
})
}}>
{this.props.children}
</MyContext.Provider>
)
}
}
export default MyProvider;
// Ok so now I am basically skipping the parent and showing you the consumer grand-child
Person.js
import React, { Component } from 'react';
// first we will make a new context
import { MyContext } from '../MyContext';
class Person extends Component {
render() {
return (
<div className="person">
<MyContext.Consumer>
{(context) => (
<React.Fragment>
<p>Age: {context.state.age}</p>
<p>Name: {context.state.name}</p>
<button onClick={context.growAYearOlder}>🍰🍥🎂</button>
</React.Fragment>
)}
</MyContext.Consumer>
</div>
)
}
}
export default Person;
2.)
// Ok so as you can see here I have had to immediately use the context.growAYearOlder. What I want to do instead is have control of it using javascript and modify it as desired; So something like this:
Child.js
const parentContext = MyContext.getContext();
if(somethingHappens){
parentContext().growAYearOlder();
}
return(
// The now rendered component
);
I tried something like this but it doesnt work:
MyContext.Consumer.context.growAYearOlder();
There are many similar questions with proper answers, docs, examples and so on - but this question kept popping up for me.
So, in case you want to get the context value and use it within your component's render() just import it (export context itself not only provider) and use _currentValue e.g.
const contextData = MyContext._currentValue;
Note that you still have to wrap your components with your given context provider.
Also note that for function components, you need to use useContext e.g.
const contextData = useContext(MyContext);
And for class components you can assign the context to a static var and then use it e.g.
class Main extends React.Component(){
static contextType = MyContext;
componentDidMount(){
const contextData = this.context;
}
render() {
return (
<p>Hey</p>
);
}
Note that the static var has to be called contextType otherwise this.context won't hold the MyContext data.
I've based my answer solely from the docs itself(https://reactjs.org/docs/context.html#updating-context-from-a-nested-component)
import React, { Component } from 'react';
import { MyContext } from '../MyContext'
class MyProvider extends Component {
constructor(props) {
super(props)
// I've moved the state declaration inside the constructor
this.state = {
name: 'Wes',
age: 100,
cool: true
}
// moved the function here and added prevState
this.growAYearOlder = () => {
this.setState(prevState => ({
age: prevState.age + 1,
}))
};
}
render() {
return (
<MyContext.Provider value={{
state: this.state,
growAYearOlder: this.growAYearOlder,
}}>
{this.props.children}
</MyContext.Provider>
)
}
}
export default MyProvider;

Default function props in functional component

So I'm looking through several SO questions and each example pertains to a Class based component not a functional component.
So I have a Container ListContainer that renders List and I'm passing toggleDrawer(). I'm unable to define toggleDrawer() in the List.defaultProps
ListContainer.jsx
import React, { Component } from 'react';
import List from './List';
class ListContainer extends Component{
constructor(props){...}
const toggleDrawer = () => {...}
render(){
return(
<List data={data} toggleDrawer={toggleDrawer}/>
)
}
}
...export statement...
List.jsx
import React from 'react';
import PropTypes from 'prop-types';
function List(props){
const { data, toggleDrawer } = props;
const openDrawer = () => toggleDrawer();
const renderListItems = (items) => {//renders a list};
return(
<ul>{renderListItems(data)}</ul>
)
}
List.propTypes = {
toggleDrawer: PropTypes.func,
};
List.defaultProps = {
toggleDrawer: <<<<<<<<<<<<<<<< Not sure how to define toggleDrawer() here
}
...export statement...
The problem I'm running into is I've tried using getDefaultProps() and maybe it's not being implemented correctly but that hasn't worked. All the examples I've looked at are using State components and so trying to use .bind(this) or this.toggleDrawer.this(bind) or any of the other examples I've tried aren't working either.
What am I missing here? Or would it be better practice to just have toggleDrawer: PropTypes.func.isRequired. That does remove the ESLint error, but I'm not 100% on that function always being required
What you probably want is a noop:
List.defaultProps = { toggleDrawer: () => {} };
The advantage of this is that you can be sure that this.props.toggleDrawer is a function even if no value was specified, which means you can safely call it without checking. Another alternative is to set the default to null, and then check that the prop is a function before calling it:
if(typeof this.props.toggleDrawer === 'function') { /* call function */ }
For the record it doesn't make much sense to define another callback (openDrawer()) which simply calls toggleDrawer. You may as well just call toggleDrawer directly.
Just do:
List.defaultProps = {
toggleDrawer: function () {
// enter code here
}
}
or arrow functions:
List.defaultProps = {
toggleDrawer: () => {
// enter code here
}
}
You can also write like this concise style :
List.defaultProps = {
toggleDrawer() {}
};

Categories

Resources