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

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.

Related

How to call function in map loop (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'));

How to map floating number from sqlite db to TextInput and backward in React Native and redux?

I'm getting a floating number from sqlite db and setting up it in redux state. Than I'm showing this property to TextInput component. To do this, I have to convert floating number to string. While editing value, I trigger event onChangeText, convert string to floating number and update redux state.
When I clear last char after point in a TextInput, my point also clearing because of converting property value from number to string. How can I save point in this case? And what's the wright way to work with floating values in react-redux?
My custom component code:
import React from 'react';
import PropTypes from 'prop-types';
import { View, TextInput } from 'react-native';
class FormFieldNumeric extends React.PureComponent {
constructor() {
super();
this.state = {
textValue: ''
}
}
componentWillReceiveProps(nextProps, nextContext) {
if (parseFloat(this.state.textValue) !== nextProps.value) {
this.setState({
textValue: nextProps.value ? String(nextProps.value) : ''
})
}
}
onChangeText = text => {
if (!text) {
this.changeValue('');
return;
}
if (text.length === 1) {
if (!'0123456789'.includes(text)) {
return;
}
}
const lastSymbol = text[text.length - 1];
if ('1234567890.,'.includes(lastSymbol)) {
if (text.split('').filter(ch => ch === '.' || ch === ',').length > 1) {
return;
}
if (lastSymbol === ',') {
this.changeValue(this.state.textValue + '.');
return;
}
this.changeValue(text);
}
};
changeValue = text => {
this.setState({
textValue: text
});
this.props.onChange(text ? parseFloat(text) : 0);
};
render() {
const { caption, value, onChange, placeholder } = this.props;
return (
<View>
<TextInput
value={this.state.textValue}
keyboardType="numeric"
onChangeText={this.onChangeText}
placeholder={placeholder}
maxLength={10}
/>
</View>
)
}
}
FormFieldNumeric.propType = {
placeholder: PropTypes.string,
value: PropTypes.number,
onChange: PropTypes.func.isRequired
};
export default FormFieldNumeric;
One option would be to only valid and update the value in your redux store when the user is finished editing vs on every keystroke. You might use the onEndEditing TextInput callback to accomplish this.
Understood what was my mistake. I fell into the anti-pattern trap when I try to keep the same state in two places. This article describes in detail this. According to the recommendations from the article, I used an uncontrolled component and stored the state directly in the component, and I only pass the property in order to initialize the value.
import React from 'react';
import PropTypes from 'prop-types';
import { View, TextInput } from 'react-native';
class FormFieldNumeric extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
defaultValue: props.defaultValue,
textValue: this.floatToTextValue(props.defaultValue)
}
}
floatToTextValue = value => {
return value ? String(value) : '';
};
render() {
const { placeholder } = this.props;
return (
<View>
<TextInput
value={this.state.textValue}
keyboardType="numeric"
onChangeText={this.onChangeText}
placeholder={placeholder}
/>
</View>
)
}
}
FormFieldNumeric.defaultValue = {
placeholder: '',
defaultValue: 0
};
FormFieldNumeric.propType = {
placeholder: PropTypes.string,
defaultValue: PropTypes.number,
onChange: PropTypes.func.isRequired
};
export default FormFieldNumeric;
And for the component to update the values ​​after loading the redux state, I made the _isLoading field in the parent component, which is true by default, but becomes false after the data is loaded. I passed this value as the key property of the parent component:
class ParentComponent extends React.PureComponent {
_isLoading = false;
async componentDidMount() {
await this.props.onCreate();
this._isLoading = false;
}
render() {
return (
<View key={this._isLoading}>
<FormFieldNumeric
defaultValue={this.props.cashSum}
onChange={this.onChangeCashSum}
placeholder="0.00"
/>
</View>
)
}
}

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>
);
}
}

React Native - setState from array

I'm trying create-react-native-app for the first time and I want to change text on varying time intervals. But my code only gives me the last item of the array.
import React from 'react';
import { Text } from 'react-native';
const blinkText = [
{
text: "A",
time: 500,
},
{
text: "B",
time: 1000,
},
{
text: "C",
time: 1000,
},
];
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
componentDidMount() {
this.interval = setInterval(() => {
blinkText.map(value => this.setState(value))
}, this.state.time);
}
componentWillUnmount() {
clearInterval(this.interval);
}
render() {
return(
<Text>{this.state.text}</Text>
);
}
}
I know I have my problem at componentDidMount() but I could not think of a way. Please take a look at my code and modify. Thanks.
Try this
componentDidMount(){
blinkText.map(e => {
setTimeout(() => {
this.setState(
prevState => ({
text: [...prevState.text, e]
});
);
}, e.time);
});
}
Note that, this.stat.text is an array, so you should render it inside your render() method by applying map()
Example:
{ this.state.text.map((e, i) => {
return (
<Text key={i}>{e}</Text>
);
})}

use flatlist instead scrollview

I've the following code, it works fine I can connect to an API and fetch the data, since I'm getting a huge list of threads how can I refactor the code using Flatlist instead?
thanks
import React, { Component } from 'react';
import { ScrollView } from 'react-native';
import axios from 'axios';
import ThreadDetail from './ThreadDetail';
class TopicList extends Component {
state = {
threads: []
};
componentWillMount() {
axios.get('https://xxxxxxx.devmn.net/api/v1/forums/threads?topic_id=2418', {
headers: {
'client-id': 'a0f21e'
}
})
.then(response => this.setState({ threads: response.data.threads }));
}
renderThreads() {
return this.state.threads.map(thread =>
<ThreadDetail key={thread.thread.id} thread={thread.thread} />
);
}
render() {
return (
<ScrollView style={styles.listStyle}>
{this.renderThreads()}
</ScrollView>
);
}
}
const styles = {
listStyle: {
backgroundColor: 'purple'
}
}
export default TopicList;
export default class TopicList extends Component {
constructor() {
super(props);
this.state = {
threads: []
}
}
componentWillMount() {
.... // same as your code
}
renderItem({index, item}) {
return <ThreadDetail thread={item.thread} />
}
render() {
return <View>
<FlatList
data={this.state.threads}
renderItems={this.renderItem}
keyExtractor={(item, index) => item.thread.id} />
</View>
}
}
note: I haven't tested this