I was having a problem with render another view in React Native.
Currently, I was trying to display another view(render another view) on click of a button. Here is my React Native code:
'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
View,
Text,
ScrollView,
Image,
TextInput,
Button
} = React;
var Button = require('./node_modules/react-native-button');
var TemplateApp = React.createClass({
_handlePress: function(event) {
// CODE TO DISPLAY ANOTHER VIEW
},
render: function() {
return (
<View>
<Button style =
{{
fontSize: 20,
height: 40,
padding: 5,
margin: 10,
backgroundColor: 'black',
color: 'green'
}}
styleDisabled = {{color: 'red'}}
onPress = {
this._handlePress
}
>
Sign In
</Button>
</View>
);
}
});
var homeApp = React.createClass({
render: function() {
return ( < View >
< Text > Welcome Home < /Text> < /View>
)
}
})
AppRegistry.registerComponent('App', () => TemplateApp);
On click of the button, inside the _handlePress function I want to display the home view. Can anyone point how to do that?
You could solve it by using state and render different content accordingly. Something like this:
var TemplateApp = React.createClass({
getInitialState: function() {
return {buttonPressed: false};
},
_handlePress: function(event) {
this.setState({buttonPressed: true}
},
render: function() {
if (!this.state.buttonPressed) {
return ( < View >
< Button style = {
{
fontSize: 20,
height: 40,
padding: 5,
margin: 10,
backgroundColor: 'black',
color: 'green'
}
}
styleDisabled = {
{
color: 'red'
}
}
onPress = {
this._handlePress
} >
Sign In < /Button>
< /View>
);}
else {
return <HomeApp />
}
}
});
var HomeApp = React.createClass({
render: function() {
return ( < View >
< Text > Welcome Home < /Text> < /View>
)
}
})
AppRegistry.registerComponent('App', () => TemplateApp);
Related
I have a React app with 2 separate components in a parent component: a dropdown component ( SearchDropdown) and an autocomplete textbox component (Autocomplete).
<div className="sidebar" style={{
borderLeft: "1px solid gray"
}}>
<h2 style={{ textAlign: "center", color: "grey" }}>Filter By:</h2>
<hr style={{ color: "grey", marginBottom: "20px" }} />
<form onSubmit={(e) => {
e.preventDefault();
const { state } = autoCompleteRef.current;
const keys = searchDropdownRef.current.state.userInput;
callSearchAPI(state.userInput, keys);
}}>
<SearchDropdown ref={searchDropdownRef}
onSearchDropdownChange={listHandler}
/>
<hr style={{ color: "grey", marginBottom: "20px" }} />
<label style={{ color: "grey" }}>Enter Value</label> <br />
<Autocomplete ref={autoCompleteRef}
suggestions={autoData}
style={{ marginBottom: "10px" }} />
<button className="btn btn-primary" > Search</button>
</form>
</div >
I have a modest goal here. Whenever the dropdown selection changes, I want to clear any text in the Autocomplete textbox. I have tried using a DOM selector in my listHandler() function called in the SearchDropdown component's `onSearchDropdownChange event. This method works in the browser console:
function listHandler(searchKey) {
document.getElementById("autocomplete").value = "";
setKey(searchKey);
const auto_key = { searchKey };
let temp = "";
if (auto_key.searchKey == 'name') {
temp = { namesData };
return setAutoData(temp.namesData);
} else if (auto_key.searchKey == 'title') {
temp = { titleData };
return setAutoData(temp.titleData);
} else if (auto_key.searchKey == 'email') {
temp = { emailData };
return setAutoData(temp.emailData);
} else if (auto_key.searchKey == 'phone') {
temp = { phoneData };
return setAutoData(temp.phoneData);
} else if (auto_key.searchKey == 'county') {
temp = { countyData };
return setAutoData(temp.countyData);
} else if (auto_key.searchKey == 'affiliation') {
temp = { affiliationData };
return setAutoData(temp.affiliationData);
} else {
return setAutoData([]);
}
}
Why doesn't this work in the code but does work in the browser? How can I clear this textbox when the dropdown selection changes?
To resolve this, I first had to add a handleReset function in my Autocomplete component:
class Autocomplete extends Component {
constructor(props) {
super(props);
this.state = {
activeSuggestion: 0,
filteredSuggestions: [],
showSuggestions: false,
userInput: ""
};
}
handleReset = () => {
this.setState({
userInput: ""
});
};
In my parent component, I had already added useRef() to reference my Autocomplete and SearchDropdown components.
export const Table = () => {
//For Sidebar Search
const autoCompleteRef = useRef();
const searchDropdownRef = useRef();
I then called my original listHandler function when the SearchDropdown component selection changed and added my reference to the handleReset function using the AutocompleteRef like this:
function listHandler(searchKey) {
document.querySelector('input[id=autocomplete]').value = "";
autoCompleteRef.current.handleReset();
...
}
It works now.
I'm starting to use React, and I want to add a react-tree component in my project. I am trying to a new node with the help of input and pass those data into the JSON array. But React Sortable tree not working.
I got the output in my console window. I have added the sample functionality here. would any please help me with this? Thanks for the response!!
I have One Parent Component named APP.js with two more child component with the names are Add.js & Drag.js
App Javascript file Sample code as below
import React, {
useState,
Component,
useEffect
} from "react";
import 'react-sortable-tree/style.css';
import TreeView from "./Drag&Drop";
// import Test from "./Testing";
import AddEdit from "./Add";
import './styles.css'
const Tree = (props) => {
const [info, setInfo] = useState('');
const data = (item) => {
let value = item.title;
setInfo(value);
}
console.log('data', info)
return ( <
div >
<
div className = "add-dt" >
<
div className = "left-side" >
<
AddEdit callback = {
data
}
/> <
/div> <
div className = "right-side" >
<
TreeView info = {
info
}
/> <
/div> <
/div> {
/* <Test /> */ }
<
/div>
);
}
export default Tree;
Two other component code are below followed with add.js & drag.js
ADD component js file
import React, {
useState
} from 'react';
import {
TextField
} from '#fluentui/react/lib/TextField';
import {
DefaultButton,
PrimaryButton,
Stack,
IStackTokens
} from '#fluentui/react';
import './styles.css'
const TextFieldBasicExample = (props) => {
const [newItem, setNewItem] = useState({
title: ''
});
console.log('onchange', newItem);
const handleChange = (e) => {
setNewItem({
[e.target.name]: e.target.value
});
}
const addData = (event) => {
console.log('onclick', newItem);
props.callback(newItem);
}
return ( <
Stack horizontal >
<
Stack className = "add-inp" >
<
TextField label = "Add Item"
placeholder = "enter text"
name = "title"
onChange = {
handleChange
}
/> <
span id = "error_name" > < /span> <
PrimaryButton text = "Add"
className = "add-btn"
onClick = {
addData
}
/>
<
/Stack> <
/Stack>
);
};
export default TextFieldBasicExample
Drag Component JS file
import React, {
useState,
Component,
useEffect
} from "react";
import 'react-sortable-tree/style.css';
import {
removeNodeAtPath
} from 'react-sortable-tree';
import SortableTree from 'react-sortable-tree';
import {
toggleExpandedForAll
} from 'react-sortable-tree';
import './styles.css'
const Treeview = (props, reset) => {
console.log('props', props)
const initTreeData = [{
title: 'Data_1',
children: [{
title: "Data_2"
}]
},
{
title: 'Data_1'
},
{
title: 'Data_2'
}
]
console.log('test', initTreeData.length)
var test = {
index: initTreeData.length + 1,
title: props.info
}
useEffect(() => {
_fetchGeneral();
}, [])
const [treeData, setTreeData] = useState(initTreeData);
console.log(treeData, "*******")
if (test.title != '') {
var m = treeData.push(test)
// setTreeData(m);
}
const _fetchGeneral = async () => {
setTreeData(initTreeData);
}
const updateTreeData = (e) => {
setTreeData(e);
}
// Expand and collapse code
const expand = (expanded) => {
setTreeData(toggleExpandedForAll({
treeData: treeData,
expanded,
}), );
}
const expandAll = () => {
expand(true);
}
const collapseAll = () => {
expand(false);
}
// Expand and collapse code end
// remove node
const removeNode = (rowInfo) => {
let {
node,
treeIndex,
path
} = rowInfo;
setTreeData(removeNodeAtPath({
treeData: treeData,
path: path, // You can use path from here
getNodeKey: ({
node: TreeNode,
treeIndex: number
}) => {
console.log(number, 'event');
return (number);
},
ignoreCollapsed: false,
}))
}
// remove node end
return ( <
div style = {
{
display: 'flex',
flexDirection: 'column',
height: '100vh'
}
} >
<
div style = {
{
flex: '0 0 auto',
padding: '0 15px'
}
} >
<
h3 > Full Node Drag Theme < /h3> <
button onClick = {
expandAll
} > Expand All < /button> <
button onClick = {
collapseAll
} > Collapse All < /button> &
nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;
<
/div>
<
div style = {
{
flex: '1 0 50%',
padding: '0 0 0 15px'
}
} >
<
SortableTree className = "tree-dt"
id = "add_name"
treeData = {
treeData
}
onChange = {
updateTreeData
}
generateNodeProps = {
rowInfo => ({
buttons: [ <
div >
<
button label = 'Delete'
onClick = {
() => removeNode(rowInfo)
} > X < /button> <
/div>,
],
style: {
height: '50px',
}
})
}
canDrag = {
({
node
}) => !node.dragDisabled
}
/> <
/div> <
/div>
);
}
export default Treeview;
I have attached the output screen as well.
When I move the page using the library react-native-tab-navigator of these navigators to move the componentDidMount page it can only be done once and after that, the lifecycle component does not work, ask for the solution: following my code.
I have opened an issue on Github, I have tried sending the state to the parent. I have used
react-native-tab-navigator version 0.3.4
class MainTab extends Component {
state = {
selectedTab: 'home'
};
render() {
return (
<
TabNavigator.Item selected = {
this.state.selectedTab === 'home'
}
title = "Home"
selectedTitleStyle = {
{
color: "#FF7158",
}
}
tabStyle = {
{
borderTopWidth: this.state.selectedTab === 'home' ? 3 : 0,
borderTopColor: '#FF7158',
backgroundColor: this.state.selectedTab === 'home' ? '#fff8f6' : '#FFFFFF'
}
}
renderIcon = {
() => < Image source = {
require('allComponents/images/ic_beranda.png')
}
style = {
{
width: 18,
height: 18
}
}
/>}
renderSelectedIcon = {
() => < Image source = {
require('allComponents/images/ic_beranda-actives.png')
}
style = {
{
width: 18,
height: 18
}
}
/>}
// renderBadge={() => <View style={{width: 20, height:20, backgroundColor:'#FF7158', borderRadius:50}}><Text style={{fontSize:12, textAlign:'center', color:'white', fontWeight:'600'}}>2}
onPress = {
() => this.setState({
selectedTab: 'home'
})
} >
<
/TabNavigator.Item> <
TabNavigator.Item
selected = {
this.state.selectedTab === 'profile'
}
title = "Pemesanan"
selectedTitleStyle = {
{
color: "#FF7158",
}
}
tabStyle = {
{
borderTopWidth: this.state.selectedTab === 'profile' ? 3 : 0,
borderTopColor: '#FF7158',
backgroundColor: this.state.selectedTab === 'profile' ? '#fff8f6' : '#FFFFFF'
}
}
renderIcon = {
() => < Image source = {
require('allComponents/images/ic_pemesanan-inactive.png')
}
resizeMode = 'stretch'
style = {
{
width: 18,
height: 18
}
}
/>}
renderSelectedIcon = {
() => < Image source = {
require('allComponents/images/ic_pemesanan-active.png')
}
resizeMode = 'stretch'
style = {
{
width: 18,
height: 18
}
}
/>}
onPress = {
() => this.setState({
selectedTab: 'profile'
})
} >
<
/TabNavigator.Item> <
TabNavigator.Item
selected = {
this.state.selectedTab === 'riwayat'
}
title = "Akun"
selectedTitleStyle = {
{
color: "#FF7158",
}
}
tabStyle = {
{
borderTopWidth: this.state.selectedTab === 'riwayat' ? 3 : 0,
borderTopColor: '#FF7158',
backgroundColor: this.state.selectedTab === 'riwayat' ? '#fff8f6' : '#FFFFFF'
}
}
renderIcon = {
() => < Image source = {
require('allComponents/images/ic_akun-inactive.png')
}
resizeMode = 'stretch'
style = {
{
width: 18,
height: 18
}
}
/>}
renderSelectedIcon = {
() => < Image source = {
require('allComponents/images/ic_akun-active.png')
}
resizeMode = 'stretch'
style = {
{
width: 18,
height: 18
}
}
/>}
onPress = {
() => this.setState({
selectedTab: 'riwayat'
})
} >
<
/TabNavigator.Item>
);
}
}
I expect that componentDidMount can function on TabBar.
componentDidMount won't trigger when it is inside a tabNavigator (expect for the first time the component gets mounted).
The reason is that when switching from a tab to another, every tab gets rendered a first time, leaving all the tabs rendered without unmounting them.
I don't know which navigator you are using, but usually you have a way to know when a screen gets 'focussed' and when it gets 'blurred'. Using those you can trigger a function when you have the screen passing from blurred to focussed.
I have two pens, and I'm trying to use a React component I defined in one pen inside another, but I'm not clear on how Codepen actually handles React imports between pens. I went to the destination pen and added the source pen's address to the Javascript references, but I don't know how to proceed from there. I can get this to work in a local node project using traditional export, but the Codepen element is giving me trouble. Here's the code:
SOURCE (https://codepen.io/ejpg/pen/LmOVoR):
export default class Wheel extends React.Component // Export default causes error
{
constructor(props){
super(props);
this.state = {
spin : false,
value: 0
};
this.spin = this.spin.bind(this);
}
spin(e){
var val = this.state.value + 720 + (Math.floor(Math.random() * 24) * 15);
console.log((this.state.value % 360) / 15);
e.target.style.webkitTransform = 'rotate(' + -val + 'deg)';
e.target.style.webkitTransition = '-webkit-transform 4s ease-out';
this.setState({value: val});
}
render(){
const wheelVals = [800, "BANKRUPT", 200, 300, 350, 250, 400, 300, 200, 250, 500, 350, 250,
"BANKRUPT", 200, 300, 400, 250, 600, "LOSE A TURN", 200, 300, 250, 200];
return (<div><img width="400" height="400" src="https://orig00.deviantart.net/0a38/f/2010/242/f/6/singapore_wheel_of_fortune_by_wheelgenius-d2xmb9v.jpg" onClick={(e) => this.spin(e)}/><br/><br/>{wheelVals[(this.state.value % 360) / 15]}
</div>);
}
}
DESTINATION (https://codepen.io/ejpg/pen/bMgWpN):
let { Grid, Row, Col, ButtonToolbar, Button } = ReactBootstrap;
// How do I import the class?
class CustomButton extends React.Component {
onHandleClick = () => {
this.props.onClick();
};
render(){
return <Button bsStyle={this.props.bsStyle} onClick={this.onHandleClick}><strong>{this.props.text}</strong></Button>;
}
}
class Letter extends React.Component {
onHandleClick = () => {
this.props.onClick(this.props.letter);
};
render () {
const style = { border: '1px solid black',
display: 'inline-block',
fontSize: '3.5vw',
width: '4vw',
height: '10vh',
textAlign: 'center',
whiteSpace: 'no-wrap',
overflow: 'hidden'};
if (this.props.letter === ' ') style.border = '';
return (
<div
style={style}
key={this.props.key}
onClick={this.onHandleClick} // Have to pass onClick to div
>
{this.props.letter}
</div>
);
}
}
class MyComponent extends React.Component {
constructor(props) {
super(props);
var blanks = '';
for (var i = 0; i < this.props.answer.length; ++i)
{
this.props.answer[i] === ' ' ?
blanks += ' ': blanks += '-';
}
this.state = {
phrase: blanks,
alpha: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
bonus: false,
revealed: false
};
this.callLetter = this.callLetter.bind(this);
this.bonusRound = this.bonusRound.bind(this);
this.complete = this.complete.bind(this);
}
replaceAt(str, index, replacement) {
return str.substr(0, index) + replacement + str.substr(index + replacement.length);
}
complete(){
if (this.state.revealed === false)
{
this.setState({phrase: this.props.answer, revealed: true});
}
}
checkForLetter(letter, phr)
{
this.setState((prevState, props) => {
var prephrase = prevState.phrase;
var index = phr.indexOf(letter);
while( index !== -1)
{
prephrase = this.replaceAt(prephrase, index, letter);
index = phr.indexOf(letter, index + 1);
}
return ({phrase: prephrase});
});
}
callLetter(letter) {
this.setState((prevState, props) => {
var alphaclone = prevState.alpha;
var letterindex = alphaclone.indexOf(letter);
alphaclone = alphaclone.slice(0, letterindex) + alphaclone.slice(letterindex + 1);
return ({alpha: alphaclone});
});
this.checkForLetter(letter, this.props.answer);
}
bonusRound(){
if (this.state.bonus === false)
{
this.callLetter('R');
this.callLetter('S');
this.callLetter('T');
this.callLetter('L');
this.callLetter('N');
this.callLetter('E');
this.setState({bonus: true});
}
}
render() {
return (
<Grid>
<Row className="show-grid" >
{
this.state.phrase.split(' ').map((item, j) =>
(
<div style = {{display:'inline-block'}}>
<Letter letter = {' '}/>
{item.split('').map((item, i) =>
(
<Letter letter= {item}/>
)) }
</div>
))
}
</Row>
<Row className="show-grid" style={{margin: '3vh'}}>
{
this.state.alpha.split('').map((item, i) =>
(
<Letter letter={item} key={i} onClick={this.callLetter}/>
))
}
</Row>
<Row className="show-grid" style={{margin: '3vh'}}>
<ButtonToolbar>
<CustomButton bsStyle = {"primary"} text= {"BONUS ROUND"} onClick = {this.bonusRound}/>
<CustomButton bsStyle = {"danger"} text= {"REVEAL ALL"} onClick = {this.complete}/>
</ButtonToolbar>
</Row>
</Grid>
);
}
}
ReactDOM.render(
<MyComponent answer='A VERY VERY EXCESSIVELY LONG TEST'/>,
document.getElementsByClassName('container-fluid')[0]
);
Any help is greatly appreciated.
EDIT: I can't believe I actually have to explicitly state that I don't want to copy and paste it.
For that you have to make your pen containing the component as a module. You can do this by going to Settings > Javascript and checking the Add type="module" checkbox.
Then you can import the component in another pen using the URL of your pen:
import MyComponent from 'https://codepen.io/user/pen/xyz.js';
The entire doc regarding this may be found here: https://blog.codepen.io/2017/12/26/adding-typemodule-scripts-pens/.
Hope this helps :)
I am super stuck on something. While I understand how a parent can pass props down to a child, I can't figure out how to use a child to communicate back up to a parent, grandparent, etc.
Basically, I have a child that is a nested component, and I want to make it so that, upon a click of this child component, another child is rendered at the same level as parent.
Here is my code...
var Grandparent = React.createClass({
getInitialState: function() {
return {closed: true};
},
checkMenuState: function() {
if (this.state.closed == true) {
return;
}
else {
return <Child/>;
}
},
handleState: function() {
this.setState({closed: false});
{this.checkMenuState}
},
render: function() {
return <div><Parent/>{this.checkMenuState()}<OtherChild onClick={this.handleState}/></div>
}
})
var Parent = React.createClass({
render: function() {
var parentSquare={backgroundColor: 'blue', height: 400, width: 400};
return <div style={parentSquare}></div>;
}
});
var Child = React.createClass({
render: function() {
var childSquare={backgroundColor: 'orange', height: 100, width: 100, top: 0, position: 'absolute'};
return <div style={childSquare} closed={this.props.closed}></div>
}
});
var OtherChild = React.createClass({
render: function() {
var childSquare={backgroundColor: 'yellow', height: 100, width: 100, top: 100, position: 'absolute'};
return <div style={childSquare}></div>
}
});
ReactDOM.render(
<Grandparent/>,
document.getElementById('container')
);
So upon initial rendering, the page should look like this:
And then, once the yellow div is clicked, it should look like this:
As of right now, nothing is happening when I click. Here is a link to my JSFiddle:
JSFiddle
In order to allow your children to modify its parent's state you should pass a closure (a method with access to another scope) from the parent to the children. Notice that your so called "parent" is not a real parent ( :'( ) but a sibling of your child components. Only the Grandparent has inner components.
var Grandparent = React.createClass({
getInitialState: function() {
return { showChild: false }
},
displayChild: function() {
this.setState({ showChild: true })
},
render: function() {
return <div>
<Parent />
{ this.state.showChild ? <Child /> : undefined }
<OtherChild onClick={ this.displayChild } />
</div>
}
})
var Parent = React.createClass({
render: function() {
var parentSquare = {
backgroundColor: 'blue',
height: 400,
width: 400
}
return <div style={ parentSquare }></div>
}
})
var Child = React.createClass({
render: function() {
var childSquare = {
backgroundColor: 'orange',
height: 100,
width: 100,
top: 0,
position: 'absolute'
}
return <div style={ childSquare }></div>
}
})
var OtherChild = React.createClass({
render: function() {
var childSquare = {
backgroundColor: 'yellow',
height: 100,
width: 100,
top: 100,
position: 'absolute'
}
return <div style={ childSquare } onClick={ this.props.onClick }></div>
}
})
ReactDOM.render(
<Grandparent/>,
document.getElementById('container')
)
Give it a try!