Function call under onKeyPress in reactjs isn't getting called - javascript

In the below code when i enter a search string and press enter, this is becoming undefined and as a result the function is not getting called.Can anybody please help me understand why? I have tried almost everything but nothing seems to be working neither could i find any pointers to the problem i am facing.
class HomepageBody extends Component{
constructor(props){
super(props);
this.state = {
value :'',
error: null,
isLoaded: false,
array: [],
mobile: ''
}
this.readSearchString = this.readSearchString.bind(this);
this.doSomething = this.doSomething.bind(this);
}
readSearchString(event){
if(event.target.value === ''){
this.setState({
error: null,
array: ''
});
}
else{
this.setState ({
value : event.target.value
});
}
}
doSomething = () => {
fetch(`http://localhost:8080/items?search=${this.state.value}&page=1`,
{
headers: {
'Accept': 'application/json'
}
})
.then(res => res.json())
.then(
(result) => {
if(result.length != 0){
this.setState({
isLoaded: true,
array: result,
error: null
});
}
else{
this.setState({
isLoaded: true,
error : "No matches found",
array: ''
})
}
},
(error) => {
this.setState({
isLoaded: true,
error: "We are experiencing some temporary problem, please try again later"
});
}
)
}
render () {
const {mobile} = this.props;
return(
<Container>
<Header
as='h1'
content='Title'
style={{
fontSize: mobile ? '1.2em' : '3em',
fontWeight: 'normal',
marginBottom: 0,
marginTop: mobile ? '5em' : '3em',
display:'block'
}}
/>
<Input icon={<Icon name='search' inverted circular link />}
placeholder='Search .....'
style={{
fontSize: mobile ? '1em' : '1em',
fontWeight: 'normal',
marginTop: mobile ? '1em' : '1em',
width: mobile ? '280px' : '600px',
}}
onChange={ this.readSearchString }
onKeyPress={(event) => {
if(event.key === 'Enter'){
this.doSomething()
}
}}
focus
/>
</Container>
)
}
}
HomepageBody.propTypes = {
mobile: PropTypes.bool,
}
Thanks,
Vikram

Yes, thats what i had done. But it didn't work. However i figured out a solution. If i'm not using the semantic ui framework's component, then i can define the function inline for onKeyPress and it works without any problems, but when i use the semantic ui framework and use the <Input> component, i have to override the function call. So this is how i did it
<Input>
..........
.........
onKeyPress = {this.onKeyPress}
</Input>
onKeyPress= (e) => {
if(e.key === 'Enter')
this.doSomething();
}
So i presume its got to something to do with semantic ui and the way it handles events within the component.

Set an attribute of tabIndex="0" and it will work.
tabindex="0" allows elements besides links and form elements to
receive keyboard focus. It does not change the tab order, but places
the element in the logical navigation flow, as if it were a link on
the page.

Related

Cannot create property label on string error on immutable objects probably

I am getting an error which I am not able to understand or shake. What I am trying to do is that on click of a button I am trying to change the value in the text field in the form I created Howerver I am getting this error:
Cannot create property label on string for one of the instances.
Here is the function where I am trying to change the values:
getReport(ReportList) {
this.state.SPCCODE.label = 'NA';
this.state.destinationcode.label = 'NA'
}
I am declaring SPCCODE in the state as
SPCCODE: '',
destinationcode: '',
I am declaring SPCCODE as conditional render in render like so:
let DDL;
const DDLValue = servicecode.label;
if (DDLValue == 'Direct') {
DDL = <> </>;
} else if (DDLValue == 'STYD') {
DDL = <> </>;
} else {
DDL = (
<Col lg="6" style={{ marginTop: '0rem' }}>
<Label for="spcc">SPC</Label>
<Select
className="select"
id="spc"
// value={servicecode}
placeholder="Search spcCode..."
value={hide ? null : SPCCODE}
onChange={this.handleChangeSPC}
options={this.state.spcCode}
isDisabled={this.state.disable}
styles={{
control: (provided, state) => ({
...provided,
boxShadow: 'none',
// borderBottom: "1px dotted pink",
borderBottom: this.state.isEmpty4 ? '1px solid red' : '1px solid black',
}),
}}
/>
</Col>
);
}
I am handling the SPC CODE change in this function:
handleChangeSPC = SPCCODE => {
this.setState({ hide: false });
this.setState({ SPCCODE });
var spc_label = SPCCODE.label;
this.setState({ spc_label });
};
I am calling the g getReport() function from a child component table like this
passVariable() {
this.props.getReport(this.state.ReportList);
}
I am calling this onClick
On researching I am getting that may it is showing the error because the variable is immutable but have not anywhere declared it in const. Please help do not know why exactly this error is showing?
The problem is that you declare SPCCODE as string in the state then trying to access to non-existent property label inside it. It is not possible and throw type error.
To solve it, you must declare it like literal object such as:
SPCCODE: {label:''}

React does not recognize the `InputProps` prop on a DOM element

Warning: React does not recognize the InputProps prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase inputprops instead. If you accidentally passed it from a parent component, remove it from the DOM element.
I don't understand what I'm doing wrong. And I've seen many similar issues like this. But I couldn't see a proper solution.
<TextField
{...input}
{...rest}
name={input.name}
inputRef={inputRef}
autoFocus={inputRef.current === document.activeElement}
disabled={disabled || false}
multiline={rowCount ? true : false}
style={{
width: "100%",
}}
onChange={(event) => {
input.onChange(event.target.value);
}}
{...(hesapla
? {
onBlur: (e) => {
hesapla({ name: input.name, value: input.value });
},
onKeyDown: (e) => {
if (e.key === "Enter") {
hesapla({ name: input.name, value: input.value });
e.preventDefault();
}
},
}
: {})}
InputProps={{
classes,
...(inputComponent ? { inputComponent: inputComponent } : {}),
...(endAdornment ? { endAdornment: endAdornment } : {}),
}}
inputProps={{
style: {
maxHeight: (rowCount * 16).toString() + "px",
overflow: "auto",
...(rightJustify ? { textAlign: "end" } : {}),
...(!readOnly && hesapla
? { fontWeight: "bold", borderBottom: "2px solid" }
: {}),
},
readOnly: readOnly ? readOnly : false,
}}
></TextField>
The problem is with your InputProps object, according to the documentation, it uses an object, you didn't pass a proper object to it.
So, if you want to realize this issue, I suggest you create your InputProps entry as a variable and log it:
const myInputPropsObject = {
classes,
...(inputComponent ? { inputComponent: inputComponent } : {}),
...(endAdornment ? { endAdornment: endAdornment } : {}),
}
console.log(myInputPropsObject)
Note: destruction of an empty object will cause the Uncaught SyntaxError: Invalid or unexpected token issue.
to check it:
const myObject = {
name: 'testName',
...{},
}
the issue is that you are using inputProps instead of InputProps

Function returning state[i].setState is not a function

What I've tried and my issue
I started with creating an external function and running it through the onClick... this works partly as it sends the alerts on click. See the services page on test.ghostrez.net.
Click the small images to trigger the alerts that show which if statement, thestate.active:value, and the state.id:value.
So I know the correct statements are being triggered.
My problem is I keep having state[i].setState is not a function returned rather than the state being set as intended.
I have placed the function internally and externally to the class Player and it returned the same issue.
I converted the function to an internal arrow function as suggested HERE.
I converted it to a const changeActiveField = () => {stuff in here}
I attempted to bind it const changeActive = changeActiveField.bind(this) *as suggested HERE and HERE
Each attempt returning the same Error
this is what the debug console returns
Here is my current function its process > 1. if the active object in state has the same id as image clicked - do nothing, 2. if the active object has a different id to the image clicked setState active:value to false then come back and find the object with the id === id of the image clicked and setState active:true from false.
function changeActiveField(im, state) {
console.log(state);
for (var i = 0; i < state.length; i++) {
if (state[i].active === true && state[i].id === im) {
return alert("if " + state[i].active + " " + state[i].id);
} else if (state[i].active === true && state[i].id !== im) {
alert(" elseif set false " + state[i].active + " " + state[i].id);
state[i].setState(false);
} else if (state[i].id === im) {
alert("elseif make true " + state[i].active + " " + state[i].id);
state[i].setState({ active: true });
return;
} else {
return alert("Nope");
}
}
}
changeActiveField is called here
<div className="thumbs">
{this.state.ids.map((i) => (
<>
<Image
className="carouselitem"
rounded
onClick={() => changeActiveField(i.id, this.state.ids)}
src={"http://img.youtube.com/vi/" + i.id + "/hqdefault.jpg"}
size="small"
/>
<h2>
{i.id} {i.active ? "true" : "false"}
</h2>
</>
))}
</div>
No joke I've been trying to resolve this for 4 days now. I'm stumped.
It appears that you are trying to setState on an individual id, but what you are actually doing is trying to call id.setState
From the code you supplied, each id looks basically like this:
{active: //true/false, id: //some Int}
but in reality your code is looking for this...
{active: //true/false, id: //some Int, setState: () => //do something here}
You'll need to handle how to find your specific id object in that array of ids, and then update your full state with the current state AND the modification you are making.
EDIT://my fault, wasn't thinking.
I would recommend making a copy of your state array in a new variable, then mapping through that new array variable making your mutations. Then set your state based on that new array objects...
let newIdArr = this.state.ids
newIdArr.map(id => //do your stuff here...)
this.setState({...this.state, ids: newIdArr})
Lastly, when you setState(false) you are overwriting ALL your state to where it will be just false, losing all your ids along the way.
This is the end product of too many days pulling my hair out... but it works now and hopefully, it helps someone else. (full component code last)
I used an anonymous function in the Image that is being rendered. This finds and updates the object in the this.state array, first, it finds the ids that don't match the value passed in from the "carouselitem" and updates their active values to false, then it finds the id that matches the value passed in and updates it to true.
The old function changeActiveField is now
onClick={() => {
this.setState((prevState) => ({
ids: prevState.ids.map((ob) =>
ob.id !== i.id
? { ...ob, active: false }
: { ...ob, active: true }
),
}));
}}
I have also moved my firstActiveId into the class. This finds the array object with active: true and returns the id value which is placed in the activevid to display and play the appropriate video.
firstActiveId = () => {
for (var i = 0; i < this.state.ids.length; i++) {
if (this.state.ids[i].active) {
return this.state.ids[i].id;
}
}
};
The firstActiveId is used like this to provide playback.
<div className="activevid">
<Embed
active
autoplay={true}
color="white"
hd={false}
id={this.firstActiveId(this.state.ids)}
iframe={{
allowFullScreen: true,
style: {
padding: 0,
},
}}
placeholder={
"http://img.youtube.com/vi/" +
this.firstActiveId(this.state.ids) +
"/hqdefault.jpg"
}
source="youtube"
/>
</div>
TIP: don't over-complicate things like I do
Full Component
import React, { Component } from "react";
import { Embed, Image } from "semantic-ui-react";
import "./Player.css";
export default class Player extends React.Component {
constructor(props) {
super(props);
this.state = {
ids: [
{
id: "iCBvfW08jlo",
active: false,
},
{
id: "qvOcCQXZVg0",
active: true,
},
{
id: "YXNC3GKmjgk",
active: false,
},
],
};
}
firstActiveId = () => {
for (var i = 0; i < this.state.ids.length; i++) {
if (this.state.ids[i].active) {
return this.state.ids[i].id;
}
}
};
render() {
return (
<div className="carouselwrap">
<div className="activevid">
<Embed
active
autoplay={true}
color="white"
hd={false}
id={this.firstActiveId(this.state.ids)}
iframe={{
allowFullScreen: true,
style: {
padding: 0,
},
}}
placeholder={
"http://img.youtube.com/vi/" +
this.firstActiveId(this.state.ids) +
"/hqdefault.jpg"
}
source="youtube"
/>
</div>
<div className="thumbs">
{this.state.ids.map((i) => (
<>
<Image
className="carouselitem"
rounded
onClick={() => {
this.setState((prevState) => ({
ids: prevState.ids.map((ob) =>
ob.id !== i.id
? { ...ob, active: false }
: { ...ob, active: true }
),
}));
}}
src={"http://img.youtube.com/vi/" + i.id + "/hqdefault.jpg"}
size="small"
/>
</>
))}
</div>
</div>
);
}
}

Why is the data undefined in react component?

So I'm trying to reproduce a simple example code of react-qr-scanner, but in the code below as I try to embed result in the p tag I get an error, saying objects cannot be embedded inside that. What am I doing wrong?
import React, { Component } from 'react';
import QrReader from 'react-qr-scanner';
class Scan extends Component {
constructor(props) {
super(props);
this.state = {
result : 'Hold QR Code steady and clear to scan',
}
this.previewStyle = {
height : 700,
width : 1000,
display : 'flex',
justifyContent : "center",
}
this.camStyle = {
display : 'flex',
justifyContent : 'center',
marginTop : '-50px',
}
this.textStyle= {
fontSize : '30px',
"text-align" : 'center',
marginTop : '-50px',
}
this.handleScan = this.handleScan.bind(this);
}
handleScan(data) {
this.setState({
result : data,
});
}
handleError(err) {
console.log(err);
}
render() {
return (
<>
<div className="stream-container" >
<QrReader
delay={100}
onError={this.handleError}
onScan={this.handleScan}
/>
</div>
<p style={this.resultStyle}>
{this.state.result} //here error occurs saying I cannot embed it inside here
</p>
</>
);
}
}
export default Scan;
The docs of react-qr-scanner has this exact example, so why isn't it working on mine? Please help.
In the function of handleScan, data is an object, 'Objects are not valid as a React child'.
Try to make your fuctions with arrow -
handleScan = (data) => {
this.setState({
result: data,
});
}
handleError = (err) => {
console.log(err);
}

Text in NavBar React-Native

I'm find a problem about a text in the navBar.
I use router-flux.
My problem is that I have insert the Logout at the right in the navBar, but I would show this button only at a category of user.
So If your role is "user1": You can logout.
If your role is "user2": You can't logout and you shouldn't see the "logout" text.
This is the code that I use to show the logout button:
App.js
export default class App extends Component {
static redirectLogout() {
Alert.alert("Logout", "Logout effettuato con successo");
Actions.authentication();
}
static logout() {
Utente.clearUtenteLoggato();
App.redirectLogout();
}
<Scene
key="homepageutente"
component={HomepageUtente}
type="reset"
leftTitle="Home"
leftButtonTextStyle={{color: "#ffffff"}}
onLeft={() => Actions.authentication()}
rightButtonTextStyle={{color: "#ffffff"}}
rightTitle="Logout"
onRight={() => App.logout()}
navigationBarStyle={{ backgroundColor: "#64c7c0" }}
/>
Do you know how can I do? If more information is needed, I will provide it immediately. Thank you very much
EDIT:
This is the structure of the App:
First page:
Authentication:
(you can go to)
--> LoginConsumer
--> LoginPlus
I Use a White page that is load after click on one button to check if you are logged in and what kind of user you are.
Starting.js
class Starting extends Component {
constructor(props) {
super(props);
this.state = {
loading: true
};
}
componentWillMount() {
Utente.getUtenteLoggato()
.then(dataUtenteLoggato => {
if (dataUtenteLoggato !== null) {
global.utente = new Utente(JSON.parse(dataUtenteLoggato));
Actions.homepageutente()({type: 'reset'});
} else if(Roles == "ROLE_PLUS") { // But this doesn't work :(
console.log(Roles)
Actions.loginplus();
}
else {
Actions.loginconsumer()
}
})
.catch(err => {
console.log(err);
})
.finally(() => {
this.setState({ loading: false });
});
}
So If you are and Role_Plus you can't logout.
Starting.js call the "getUtenteLoggato" from Utente:
static async getUtenteLoggato() {
try {
return await AsyncStorage.getItem("#UtenteLoggato");
} catch (error) {
console.log(error.message);
return null;
}
}
You could use a simple ternary condition to determine the state of this by checking on the user1 state:
<Scene
key="homepageutente"
component={HomepageUtente}
type="reset"
leftTitle="Home"
leftButtonTextStyle={{color: "#ffffff"}}
onLeft={() => Actions.authentication()}
rightButtonTextStyle={{color: "#ffffff"}}
rightTitle={user === "user1" ? "Logout" : ""}
onRight={user === "user1" ? () => App.logout() : () => {}}
navigationBarStyle={{ backgroundColor: "#64c7c0" }}
/>

Categories