How to call function in map loop (react native)? - react-native

This is my code. I am not sure what error exists.
When I click the image button, it calls proper function exactly.
If I click the first button, it calls toggleBooks() function correctly.
Then in that function, I want to use vidMute state value.
So I tried console.log('Video toggle', this.state.vidMute); then it gives me an error like the following image.
But if I print console.log('Video toggle'), then it works well.
How to use state value in that function?
export default class Video extends Component {
constructor(props) {
super(props)
this.state = {
vidMute: false,
audioShow: false,
callShow: false,
btn: [
{ func: this.toggleAudio, url: magic, de_url: de_magic },
{ func: this.endCall, url: endcall, de_url: de_endcall },
{ func: this.toggleBooks, url: camerarotate, de_url: de_camerarotate },
],
};
this.toggleAudio = this.toggleAudio.bind(this)
this.endCall = this.endCall.bind(this)
this.toggleBooks = this.toggleBooks.bind(this)
}
toggleBooks() {
console.log('Video toggle', this.state.vidMute);
}
endCall() {
console.log('Call toggle', this.state.audioShow);
}
toggleAudio() {
console.log('Audio toggle', this.state.callShow);
}
render() {
return (
<View>
{
this.state.btn.map((item, index) => (
<TouchableOpacity key={index} style={styles.iconStyle} activeOpacity={0.4} onPress={item.func}>
<Image source={this.state.lockState ? item.de_url : item.url} style={{ width: 70, height: 70 }} />
</TouchableOpacity>
))
}
</View>
)
}
}

this refers to the context of your function and not the context of your component. You can try to bind your method like this :
this.myMethod = this.myMethod.bind(this);
in your constructor.
Or use the fat arrow pattern (Highly recommanded) which automatically includes the binding to your component's context.
Here is a binding example on stackblitz
Here is the code :
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
class App extends Component {
constructor() {
super();
this.state = {
name: 'React',
items:[
{name:"item 1", func: () => this.test()},
{name:"item 2", func: () => this.test2()}
]
};
this.test = this.test.bind(this);
}
test() {
console.log('Hi', this.state.name);
}
test2() {
console.log('Hello', this.state.name); // Note this is not binded
}
render() {
return (
<div>
<Hello name={this.state.name} />
<p onClick={this.test}>
Start editing to see some magic happen :)
</p>
<div>
{
this.state.items.map(item => <div onClick={() => item.func()}>{item.name}</div>)
}
</div>
</div>
);
}
}
render(<App />, document.getElementById('root'));

Related

How do I perform an onAuthStateChanged in Vue Native?

I want to perform something equivalent to this:
export default class LoadingScreen extends React.Component {
componentDidMount() {
firebase.auth().onAuthStateChanged(user => {
this.props.navigation.navigate(user ? 'App' : 'Auth');
});
}
render() {
return (
<View style={styles.container}>
<Text>Loading</Text>
<ActivityIndicator size='large'></ActivityIndicator>
</View>
);
}
}
I have setup my routes to go through the Loading to check the user's auth state before proceeding to either Auth or App. When I add mounted(), the loading text and activity-indicator don't show.
<template>
<view class="container">
<nb-text>Loading</nb-text>
<activity-indicator size="large" color="#0000ff" />
</view>
</template>
<script>
import firebase from "firebase";
import Fire from "./../../api/firebaseAPI";
export default {
// Declare `navigation` as a prop
props: {
navigation: {
type: Object,
},
},
async mounted() {
await firebase.auth().onAuthStateChanged(function (user) {
this.navigation.navigate(user ? "App" : "Auth");
});
},
};
</script>
When I run this code above I get a white screen.
Maybe we should move the code in mounted to a method.
<script>
mounted(){
this.checkAuth()
},
...
methods:{
async checkAuth(){
await firebase.auth().onAuthStateChanged(function (user) {
if(user){
this.navigation.navigate("Auth")
}else{
this.navigation.navigate("App")
}
});
}
}
</script>

How to make dynamic checkbox in react native

I am making a react native application in which i need to make checkbox during runtime.I means that from server i will get the json object which will have id and label for checkbox.Now i want to know that after fetching data from server how can i make checkbox also how can i handle the checkbox , i mean that how many number of checkbox will be there it will not be static so how can i declare state variables which can handle the checkbox.Also how can i handle the onPress event of checkbox.Please provide me some help of code .Thanks in advance
The concept will be using an array in the state and setting the state array with the data you got from the service response, Checkbox is not available in both platforms so you will have to use react-native-elements. And you can use the map function to render the checkboxes from the array, and have an onPress to change the state accordingly. The code will be as below. You will have to think about maintaining the checked value in the state as well.
import React, { Component } from 'react';
import { View } from 'react-native';
import { CheckBox } from 'react-native-elements';
export default class Sample extends Component {
constructor(props) {
super(props);
this.state = {
data: [
{ id: 1, key: 'test1', checked: false },
{ id: 2, key: 'test1', checked: true }
]
};
}
onCheckChanged(id) {
const data = this.state.data;
const index = data.findIndex(x => x.id === id);
data[index].checked = !data[index].checked;
this.setState(data);
}
render() {
return (<View>
{
this.state.data.map((item,key) => <CheckBox title={item.key} key={key} checked={item.checked} onPress={()=>this.onCheckChanged(item.id)}/>)
}
</View>)
}
}
Here's an example how you can do this. You can play with the code, to understand more how it's working.
export default class App extends React.Component {
state = {
checkboxes: [],
};
async componentDidMount() {
// mocking a datafetch
setTimeout(() => {
// mock data
const data = [{ id: 1, label: 'first' }, { id: 2, label: 'second' }];
this.setState({
checkboxes: data.map(x => {
x['value'] = false;
return x;
}),
});
}, 1000);
}
render() {
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
{JSON.stringify(this.state)}
</Text>
{this.state.checkboxes.length > 0 &&
this.state.checkboxes.map(checkbox => (
<View>
<Text>{checkbox.label}</Text>
<CheckBox
onValueChange={value =>
this.setState(state => {
const index = state.checkboxes.findIndex(
x => x.id === checkbox.id
);
return {
checkboxes: [
...state.checkboxes.slice(0, index),
{ id: checkbox.id, label: checkbox.label, value },
...state.checkboxes.slice(index+1),
],
};
})
}
value={checkbox.value}
key={checkbox.id}
/>
</View>
))}
</View>
);
}
}

How to make button in OverflowSet execute?

How do I get a button in Office ui fabric's OverflowSet do something.
The example from https://developer.microsoft.com/en-us/fabric#/components/overflowset has the onClick event which never fires.
import * as React from 'react';
import { BaseComponent, css } from 'office-ui-fabric-react/lib/Utilities';
import { CommandBarButton } from 'office-ui-fabric-react/lib/Button';
import { SearchBox } from 'office-ui-fabric-react/lib/SearchBox';
import { IOverflowSetItemProps, OverflowSet } from 'office-ui-fabric-react/lib/OverflowSet';
import * as stylesImport from './OverflowSet.Example.scss';
const styles: any = stylesImport;
export class OverflowSetCustomExample extends BaseComponent<any, any> {
public render(): JSX.Element {
return (
<OverflowSet
items={[
{
key: 'upload',
name: 'Upload',
icon: 'Upload',
onClick: () => {
console.log("this never happens");
}
}
]}
overflowItems={[]}
onRenderOverflowButton={this._onRenderOverflowButton}
onRenderItem={this._onRenderItem}
/>
);
}
private _onRenderItem(item: IOverflowSetItemProps): JSX.Element {
if (item.onRender) {
return item.onRender(item);
}
return <CommandBarButton iconProps={{ iconName: item.icon }} menuProps={item.subMenuProps} text={item.name} />;
}
private _onRenderOverflowButton(overflowItems: any[] | undefined): JSX.Element {
return (
<CommandBarButton className={css(styles.overflowButton)} menuIconProps={{ iconName: 'More' }} menuProps={{ items: overflowItems! }} />
);
}
}
the click event never fires. How do I use the button?
Since you are providing an onRenderItem callback, you are taking over the component’s default render method. Therefore, you have to apply the onClick prop yourself directly:
private _onRenderItem(item: IOverflowSetItemProps): JSX.Element {
if (item.onRender) {
return item.onRender(item);
}
//
// this now returns the button with the onClick handler applied
//
return <CommandBarButton onClick={item.onClick} iconProps={{ iconName: item.icon }} menuProps={item.subMenuProps} text={item.name} />;
}

How to uncheck all other checkbox if data is "No Preference"?

How do I uncheck all checkbox if the data is no preference? I don't know how to manipulate the data.
This is the index.js:
import React, { Component } from "react";
import { Text, View } from 'react-native';
import { CheckBox } from 'react-native-elements';
import { Colors } from '../../../themes/';
import style from "./style";
class CCheckBox extends React.Component {
/////////////////////////////
// constructor()
/////////////////////////////
constructor(props, context) {
super(props, context);
console.log('custom/ccheckbox/index.js constructor()');
this.state = {
checked: false,
};
}
/////////////////////////////
// handleCheck()
/////////////////////////////
handleCheck() {
this.setState({ selectedCheckbox }); // update selected item
}
render() {
return (
<CheckBox
iconType='material'
checkedIcon='check'
uncheckedIcon='check-box-outline-blank'
checkedColor={Colors.ORANGE}
checked={this.state.checked}
containerStyle={style.content}
onPress={() => this.handleCheck()}
/>
);
}
}
export default CCheckBox;
And this is my profalcoholpref.js:
import React, { Component } from "react";
import { ScrollView, View } from 'react-native';
import { Content } from 'native-base';
import CButton from '../cbutton/index';
import PopSelectList from './popselectlist';
import styleC from "../../common/style";
import style from "./style";
class PopAlcoholPref extends React.Component {
///////////////////////////////
// constructor()
///////////////////////////////
constructor(props, context) {
super(props, context);
console.log('custom/cfield/popalcoholpref.js constructor()');
this.state = {
selectedCheckbox: {},
visible: this.props.visible,
data: [
{
id : 1,
code : 'DON',
description : 'Do not drink',
},
{
id : 2,
code : 'INF',
description : 'Infrequently',
},
{
id : 3,
code : 'SOC',
description : 'Socially',
},
{
id : 4,
code : 'MOD',
description : 'Moderately',
},
{
id : 5,
code : 'ASN',
description : 'As Needed',
},
{
id : 5,
code : 'NOP',
description : 'No Preference',
},
]
};
}
///////////////////////////////
// componentWillReceiveProps()
///////////////////////////////
componentWillReceiveProps(nextProps) {
console.log('componentWillReceiveProps()');
this.setState({
visible: nextProps.visible
});
}
///////////////////////////////
// handleSave()
///////////////////////////////
handleSave() {
console.log('handleSave()');
this.setState({
visible: false
});
}
///////////////////////////////
// render()
///////////////////////////////
render() {
return (
<View>
<PopSelectList title='Alcohol Preference' data={this.state.data} visible={this.state.visible} handleSave={() => this.handleSave()} />
</View>
);
}
}
export default PopAlcoholPref;
How do I uncheck all other checkbox if no preference is checked? Is there any way I can manipulate the data? Index.js is the frontend and I manipulated the checkbox there and in the prefalcohol is where the data is being stored.
You will need a bit of a refactoring here I beleive.
You should move the state handling logic to the list. In the list you can manipulate all the checkboxes at the same time.
class List extends Component {
constructor(props) {
super(props);
this.state = {
checkBoxesList: [{
id: 1,
checked: false,
}, {
id: 2,
checked: false,
}]
}
}
unCheckAll() {
this.setState({ checkBoxesList: this.state.checkBoxesList.map(({ id }) => ({
id: id,
checked: false,
})) })
}
checkBoxSelected(id) {
const index = this.state.checkBoxesList.findIndex((value) => value.id === id);
this.setState({ checkBoxesList[index]: {
...this.state.checkBoxesList[index],
checked: !this.state.checkBoxesList[index].checked
})
}
renderCheckBoxes() {
return this.state.checkBoxesList.map(({id, checked}) => (
<CheckBox id={id} checked={checked} onPress={this.checkBoxSelected} />
))
}
render() {
return (
<View>
{this.renderCheckBoxes()}
</View>
)
}
}
So this Component handles the states for the checkboxes. You need to make sure that you also implement the callback inside the CheckBox component for the OnPress method. Now calling the UncheckAll method will uncheck all the checkboxes.
But also you have to put in some extra check before setting the checkBoxesList if the index does exist.

test with enzyme a react component with context: return an empty object

I'm trying to execute a dummy test with enzyme over a component. the test is about to check the context. even though I'm writing the same code as enzyme's documentation the context is always empty.
import React from 'react';
import { shallow } from 'enzyme';
import Overlay from '../../../../app/components/Overlay/Overlay';
describe('<Overlay />', () => {
it.only('return a context', () => {
const wrapper = shallow(<Overlay />, { context: { foo: 10 } });
console.log(wrapper.context());
// expect(wrapper.context().foo).to.equal(10);
});
})
the test's output is:
<Overlay />
{}
✓ return a context
where am I wrong?
Since the details of Overlay component is not given, I assume the context is not used in it (pls check childContextTypes and getChildContext are defined properly)
For example, refer the explanation for contexts in react documents
I have taken the same example to enable the test,
import React from 'react';
export default class Button extends React.Component {
render() {
return (
<button style={{ background: this.context.color }}>
{this.props.children}
</button>
);
}
}
Button.contextTypes = {
color: React.PropTypes.string,
};
class Message extends React.Component {
render() {
return (
<div>
{this.props.text} <Button>Delete</Button>
</div>
);
}
}
class MessageList extends React.Component {
getChildContext() {
return { color: 'purple' };
}
render() {
const children = this.props.messages.map((message) =>
<Message text={message.text} />
);
return <div>{children}</div>;
}
}
MessageList.childContextTypes = {
color: React.PropTypes.string,
};
I've created the test for Button component as below,
import React from 'react';
import { shallow } from 'enzyme';
import { expect } from 'chai';
import Button from '../../src/components/SampleComp';
describe.only('<Button />', () => {
it('assert for context', () => {
const wrapper = shallow(
<Button />,
{ context: { color: 'red' } }
);
expect(wrapper.context().color).to.equal('red');
expect(wrapper.context('color')).to.equal('red');
});
});
<Button />
✓ assert for context
1 passing (214ms)
This will assert it correctly.