I have implemented this but the store has no values (all undefined):
This is the store:
export default class AppState {
// Is authenticated
#observable authenticated;
#action get authenticated() {
return this.authenticated;
}
doSomethingWithNoDecorator() {
return this.authenticated;
}
}
This is index.js:
const stores = {
AppState
};
const renderApp = Component => {
render(
<AppContainer>
<Provider { ...stores }>
<Router>
// Routes
</Router>
</Provider>
</AppContainer>,
document.getElementById("root")
);
};
This is the Component:
#inject("AppState")
#observer
export default class SidebarListItem extends Component {
constructor(props) {
super(props)
this.store = this.props.AppState;
}
doSomething() {
this.store.authenticated();
this.store.doSomethingWithNoDecorator();
this.store.authenticated;
}
}
The store is not null... I can see the function. But I can't get any field or invoke any method.
What did I do wrong?
Regards,
Idob
You need to initialise your store:
const stores = { AppState: new AppState() }
By the way, #actions cannot be applied to getters.
Related
Is there a way of delegating in react native just like in swift/ios.. If we want to pass a information to a child class from parent class, we can do it by passing props. But what if we want to pass some information from the child class to parent class.
PS: No Redux or singleton approach.
Callbacks are common in React and could be used for such a thing.
// Child.js
export default class Child extends Component {
componentDidMount() {
this.props.onEvent({ type : "event" });
}
render() {
return (
<Text>I'm a child</Text>
);
}
}
// Parent.js
export default class Parent extends Component {
const onChildEvent = (event) => {
console.log(event); // { type : "event" }
}
render() {
return (
<Child onEvent={this.onChildEvent} />
);
}
}
I have created a website in angular7 in which we have fire the function from 1 component to another component function is fire properly but value are not reflect in the html below we have shared updated fiddle:
//Component1.
import { Component, OnInit } from '#angular/core';
import { Router,NavigationExtras } from "#angular/router";
import {UserService} from "../../service/user.service";
import { FormGroup, FormBuilder, FormControl, FormGroupDirective, NgForm, Validators } from '#angular/forms';
import { DashboardComponent } from '../../dashboard/dashboard.component';
declare var $: any;
#Component({
selector: 'app-innerheader',
templateUrl: './innerheader.component.html',
styleUrls: ['./innerheader.component.css'],
providers : [DashboardComponent]
})
export class InnerheaderComponent implements OnInit {
//declare global varible here....
private loggedUserObject : any = {};
private userImageUrl : any;
constructor(
private router : Router,
private service : UserService,
private formBuilder: FormBuilder,
private dashboard : DashboardComponent) {
}
ngOnInit() {
}
//unblockUser for unblock user
unblockUser(user : any) {
//pass the dataparam in the backend....
var data = {
"user_id" : this.loggedUserObject.user_id,
"block_user_id" : this.selectedUser.id
}
//here we will set url via key wise....
var url = '/api/un-block-user-profile';
//saveDetail function for save data in db...
this.service.saveDetail(data, url).subscribe( (data : any) => {
if(data.status) {
$('#BlockedListModal').on('hidden.bs.modal', function () {
this.dashboard.getUserDetail();
})
//her we will remove user from the updated list of block user...
var index = this.blockUserlist.findIndex(x=>x.id == this.selectedUser.id);
if(index != -1) {
this.blockUserlist.splice(index, 1);
}
//remoive card after accept
this.currentElement.remove();
this.service.successAlert(data.message);
}
});
}
}
//header compeonet 2: here we will fire function from another compeonet
getDashboardDetail() {
//hold user info
var data = {
"user_id" : this.currentUserObject.user_id
}
var url = '/api/time-line-list';
//createUser function for create user in DB
this.service.saveDetail(data, url).subscribe( (data : any) => {
if(data.status) {
if(data.result.article_info.length >0) {
if(this.dashboardArticleList.length == 0) {
this.dashboardArticleList = data.result.article_info;
} else {
this.dashboardArticleList = this.dashboardArticleList.concat(data.result.article_info);
}
}
}
});
}
//In the 2nd Component we have show listing inside model.i have reload the list after close model. please check and tell me what the wrong in my code?
So I started converting my application from ES2015 to ES6 which uses React.
I have a parent class and a child class like so,
export default class Parent extends Component {
constructor(props) {
super(props);
this.state = {
code: ''
};
}
setCodeChange(newCode) {
this.setState({code: newCode});
}
login() {
if (this.state.code == "") {
// Some functionality
}
}
render() {
return (
<div>
<Child onCodeChange={this.setCodeChange} onLogin={this.login} />
</div>
);
}
}
Child class,
export default class Child extends Component {
constructor(props) {
super(props);
}
handleCodeChange(e) {
this.props.onCodeChange(e.target.value);
}
login() {
this.props.onLogin();
}
render() {
return (
<div>
<input name="code" onChange={this.handleCodeChange.bind(this)}/>
</div>
<button id="login" onClick={this.login.bind(this)}>
);
}
}
Child.propTypes = {
onCodeChange: React.PropTypes.func,
onLogin: React.PropTypes.func
};
However this causes the following error,
this.state is undefined
It refers to,
if (this.state.code == "") {
// Some functionality
}
Any idea what could be causing this ?
You can use arrow function to bind you functions. You need to bind you functions both in child as well as parent components.
Parent:
export default class Parent extends Component {
constructor(props) {
super(props);
this.state = {
code: ''
};
}
setCodeChange = (newCode) => {
this.setState({code: newCode});
}
login = () => {
if (this.state.code == "") {
// Some functionality
}
}
render() {
return (
<div>
<Child onCodeChange={this.setCodeChange} onLogin={this.login} />
</div>
);
}
}
Child
export default class Child extends Component {
constructor(props) {
super(props);
}
handleCodeChange = (e) => {
this.props.onCodeChange(e.target.value);
}
login = () => {
this.props.onLogin();
}
render() {
return (
<div>
<input name="code" onChange={this.handleCodeChange}/>
</div>
<button id="login" onClick={this.login}>
);
}
}
Child.propTypes = {
onCodeChange: React.PropTypes.func,
onLogin: React.PropTypes.func
};
There are other ways to bind the functions as well such as the one you are using but you need to do that for parent component too as <Child onCodeChange={this.setCodeChange.bind(this)} onLogin={this.login.bind(this)} />
or you can specify binding in the constructor as
Parent:
constructor(props) {
super(props);
this.state = {
code: ''
};
this.setCodeChange = this.setCodeChange.bind(this);
this.login = this.login.bind(this);
}
Child
constructor(props) {
super(props);
this.handleCodeChange = this.handleCodeChange.bind(this);
this.login = this.login.bind(this);
}
I agree with all different solutions given by #Shubham Kathri except direct binding in render.
You are not recommended to bind your functions directly in render. You are recommended to bind it in constructor always because if you do binding directly in render then whenever your component renders Webpack will create a new function/object in bundled file thus the Webpack bundle file size grows. For many reasons your component re-renders eg: doing setState but if you place it in constructor it gets called called only once.
The below implementation is not recommended
<Child onCodeChange={this.setCodeChange.bind(this)} onLogin={this.login.bind(this)} />
Do it in constructor always and use the ref wherever required
constructor(props){
super(props);
this.login = this.login.bind(this);
this.setCodeChange = this.setCodeChange.bind(this);
}
<Child onCodeChange={this.setCodeChange} onLogin={this.login} />
If you are using ES6 then manual binding is not required but if you want you can. You can use arrow functions if you want to stay away with scope related issues and manual function/object bindings.
Sorry if there are any typos I am answering in my mobile
I have a custom form component that implements ControlValueAccessor. This component has an internal property touched.
export class BmInputComponent implements ControlValueAccessor, Validator {
private onTouchedCallback: () => {};
private touched: boolean = false;
registerOnTouched(fn: any) {
this.onTouchedCallback = fn;
}
onBlur() {
this.touched = true;
this.onTouchedCallback();
}
}
I need to implement a method like
markTouched() {
this.touched = true;
}
That could be called by the user of the component when markAsTouched is executed in the formControl: customInputControl.markAsTouched()
I cannot find an angular-way to do this.
#Edit:
Tried to inject the NgControl:
#Component({
selector: 'bm-input',
templateUrl: './bm-input.component.html',
encapsulation: ViewEncapsulation.None,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => BmInputComponent),
multi: true
}
]
})
export class BmInputComponent implements ControlValueAccessor, Validator {
private onTouchedCallback: () => {};
private touched: boolean = false;
constructor(#Self() #Optional() public _formControl: NgControl) {
this._viewDate = new Date();
if (this._formControl) {
this._formControl.valueAccessor = this;
this._formControl.statusChanges.subscribe(this.markTouched);
}
}
registerOnTouched(fn: any) {
this.onTouchedCallback = fn;
}
onBlur() {
this.touched = true;
this.onTouchedCallback();
}
markTouched() {
if(this._formControl.touched)
this.touched = true;
}
}
But I am getting Cannot instantiate cyclic dependency! NgControl when the component is invoked with a formControl.
Have you tried #SkipSelf() instead of #Self()?
You could try this:
constructor(private injector: Injector) {
}
ngDoCheck() {
let ngControl = this.injector.get(NgControl);
if (! ngControl.control) {
return;
}
this.touched = ngControl.control.touched;
}
The circular dependency is caused by having both the NG_VALUE_ACCESSOR in your #Component(...) providers, and injecting NgControl in the constructor. These are mutually exclusive.
See the example in the NG material documentation here: https://material.angular.io/guide/creating-a-custom-form-field-control#ngcontrol
I am using React Native with Redux. The following code is used to create the Redux store, and uses AsyncStorage to check if the user is logged in by checking the presence of an authToken.
import {createStore} from 'redux';
import {persistStore} from 'redux-persist';
async function getAuthToken() {
return await AsyncStorage.getItem('authToken');
}
export function createStore(onCompletion:() => void):any {
...
const store = createStore(
reducer,
{
auth: {
authenticated: !!getAuthToken()
}
},
enhancer);
persistStore(store, {
storage: AsyncStorage,
},
onCompletion);
}
The creation of the store:
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
store: createStore(...),
};
}
render() {
return (
<Provider store={this.state.store}>
<AppNavigator />
</Provider>
);
}
}
The authToken value get correctly set once the user logs in, and is removed once the user logs out. But the authToken does not get persisted after the app is relaunched. The first call to getAuthToken always returns this junk value from AsyncStorage:
{ _45: 0, _81: 0, _65: null, _54: null }
Why could this be happening?
Now you're returning a promise from AsyncStorage, you need to return the token value. Try:
async function getAuthToken() {
return await AsyncStorage.getItem('authToken').then((token) => token);
}
With hooks you useEffect
import AsyncStorage from '#react-native-async-storage/async-storage';
import { useState, useEffect } from 'react';
export function App() {
const [token, setToken] = useState<string>();
useEffect(()=>{
(async function() {
setToken(await AsyncStorage.getItem());
await SplashScreen.hideAsync();
})();
},[]);
if (token) {
return (<View><Text>{token}</Text></View>);
} else {
return null;
}
}