Error : Cannot read property 'name' of undefined? - javascript

this is a part code file app.js
....
this.state = {
todoList: [
{ id: 1, name: "Khoa" },
{ id: 2, name: "Linh" },
{ id: 3, name: "Luc" },
],
inputText: "",
currentName: "",
todoSearch : []
};
}
....
handleSubmit = (e, inputRef) => {
const { todoList, currentName } = this.state;
if (inputRef.current.value.trim() === "")
alert("Hay nhap du lieu can input");
else {
if (currentName !== "") {
this.setState({
todoList : todoList.map(item => {
if(item.name === currentName) {
return {...item, name : inputRef.current.value}// error this code
}
}),
currentName : ''
})
} else {
const data = { id: todoList.length + 1, name: inputRef.current.value };
console.log("say hi");
this.setState({
todoList: [...todoList, data],
currentName : ''
});
}
}
};
.....
I want to update data unsatisfactorily item.name === currentName . Meaning replace name old of object in todoList equal new name is inputRef.current.value but not work. help me

Put else if the value doesn't match -
todoList : todoList.map(item => {
if(item.name === currentName) {
return {...item, name : inputRef.current.value}// error this code
}else{
return {...item}
})

Related

Updating Array from AsyncStorage

I have an array of objects called audioBaby.
When the app launches I check asyncStorage and if any key has value active, I want to update the lock keys in the array.
What I have done is not updating all objects in array but only the last object.
How can I initially update the array from asyncStorage and render the screen?
const [audioBaby, setAudioBaby] = useState([
{
lock: "deactive",
url: "item0.mp3",
},
{
lock: "deactive",
url: "item1.mp3",
},
{
lock: "deactive",
url: "item2.mp3",
},
]);
useEffect(() => {
try {
AsyncStorage.multiGet([
"babyAudio0Status", //value: active
"babyAudio1Status", //value: active
"babyAudio2Status", //value: active
]).then((response) => {
let updatedList = audioBaby;
if (response[0][1] != "null" && response[0][1] == "active") {
updatedList = audioBaby.map((item) => {
if (item.url == "item0.mp3") {
return { ...item, lock: "active" };
}
return item;
});
}
if (response[1][1] != "null" && response[1][1] == "active") {
updatedList = audioBaby.map((item) => {
if (item.url == "item1.mp3") {
return { ...item, lock: "active" };
}
return item;
});
}
if (response[2][1] != "null" && response[2][1] == "active") {
updatedList = audioBaby.map((item) => {
if (item.url == "item2.mp3") {
return { ...item, lock: "active" };
}
return item;
});
}
setAudioBaby(updatedList)
});
} catch (error) {
console.log("error::", error);
}
}, []);
Final array should be like this:
[
{
lock: "active",
url: "item0.mp3",
},
{
lock: "active",
url: "item1.mp3",
},
{
lock: "active",
url: "item2.mp3",
},
]
I moved all ifs to inside of map function and everything is fine.
let updatedList = audioBaby.map((item) => {
if (item.url === 'item0.mp3' && response[0][1] === 'active') {
return { ...item, lock: 'active' }
}
if (item.url === 'item1.mp3' && response[1][1] === 'active') {
return { ...item, lock: 'active' }
}
if (item.url === 'item2.mp3' && response[2][1] === 'active') {
return { ...item, lock: 'active' }
}
return item
})

How can i clear the chat input-box after sending the message(from suggestion) in botframework webchat?

i'm working on a bot application using react js and botframework webchat. The thing is that i want to clear the text input box (from where msgs are sent) after sending the message - which is selected from the suggestion. The Suggestion list(or autocomplete component) is a custom coded one. And What i mean is that if i type "hr" the suggestion list popup will come and if i click on one option from the suggestion, say 'hr portal', it will be sent, but what i wrote ie "hr" remains there in the input field and i want to clear that. And please note that If i type something and send its working fine. The problem is only when i type something and select something from the suggestion. Everything else is fine. How can i clear that. Any help would be really appreciated.
please find the below image for more understanding.
here's my code;
import React from 'react';
import { DirectLine, ConnectionStatus } from 'botframework-directlinejs';
import ReactWebChat from 'botframework-webchat';
import './ChatComponent.css';
var val;
var apiParameters = [];
var currentFocus = -1;
export default class extends React.Component {
constructor(props) {
super(props);
this.state = {
token: '',
conversationId: '',
directLine: {},
view: false,
feedBack: null,
value: '',
popupContent: '',
storeValue: '',
suggestions: [],
suggestionCallback: '',
suggestionTypedText: "",
typingChecking: "false",
};
this.handleTokenGeneration = this.handleTokenGeneration.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleSaveFeedback = this.handleSaveFeedback.bind(this);
this.handleSuggestion = this.handleSuggestion.bind(this);
this.handleClose = this.handleClose.bind(this);
this.handleSuggestionClick = this.handleSuggestionClick.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.moveHighlight = this.moveHighlight.bind(this);
this.getSuggestionHtml = this.getSuggestionHtml.bind(this);
}
getSuggestionHtml(suggestion) {
const lowerCaseSuggestion = suggestion.toLowerCase();
return {
__html: lowerCaseSuggestion.includes(this.state.suggestionTypedText) ? lowerCaseSuggestion
.replace(this.state.suggestionTypedText, `<b>${this.state.suggestionTypedText}</b>`) : lowerCaseSuggestion
};
}
handleTokenGeneration = async () => {
console.log("11111");
const response = await fetch(`api/TokenGenerationService/GetToken`);
const data = await response.json();
this.setState({
token: data.categoryObject.token, conversationId:
data.categoryObject.conversationId
});
this.state.directLine = new DirectLine({ token: this.state.token });
this.setState({ view: true });
this.setState({ typingChecking: "true" });
console.log("conversationId");
};
async handleSuggestion(val, store) {
if (val === "") {
this.setState({
suggestions: []
});
}
else {
apiParameters = [];
var valuess = null;
const response = await fetch(`api/TokenGenerationService/GetAzureSearch?myparam1=${val}`);
const data = await response.json();
var values = ["Hello", "yes", "no", "exit", "Welcome", "Thank You", "Approve", "Apply leave", "Reject", "Absence Balance", "Leave Balance", "Upcoming Holidays", "Apply Comp-Off", "Approve Leave", "Raise Incident Tickets", "Project Allocation Info", "Reporting Manager Change", "Reporting Manager Approval", "Approve Isolve Tickets", "My Manager", "My Account Manager", "Generate Salary Certificate", "Isolve Ticket Status", "Internal Job Posting", "My Designation", "My Joining Date", "RM Approval", "RM Change", "Resource Allocation", "ESettlement Approval", "SO Approval", "Cash advance Approval", "Purchase Request Approval", "Referral status", "HR Ticket", "Platinum Support"];
valuess = values.filter(s =>
s.toLocaleLowerCase().startsWith(val.toLowerCase())
);
valuess = valuess.concat(data.az_search);
this.setState({
suggestions: valuess,
suggestionCallback: store,
suggestionTypedText: val.toLowerCase()
});
// alert(data.az_search);
var totCount = data.az_search;
console.log("kkkkkk" + totCount);
}
}
moveHighlight(event, direction) {
event.preventDefault();
const { highlightedIndex, suggestions } = this.state;
if (!suggestions.length) return;
let newIndex = (highlightedIndex + direction + suggestions.length) % suggestions.length;
if (newIndex !== highlightedIndex) {
this.setState({
highlightedIndex: newIndex,
});
}
}
keyDownHandlers = {
ArrowDown(event) {
this.moveHighlight(event, 1);
},
ArrowUp(event) {
this.moveHighlight(event, -1);
},
Enter(event) {
const { suggestions } = this.state;
if (!suggestions.length) {
// menu is closed so there is no selection to accept -> do nothing
return
}
event.preventDefault()
this.applySuggestion(suggestions[this.state.highlightedIndex]);
},
}
handleKeyDown(event) {
// console.log("lokkkkkkkkkkkk")
if (this.keyDownHandlers[event.key])
this.keyDownHandlers[event.key].call(this, event)
}
async handleSuggestionClick(event) {
await this.applySuggestion(event.currentTarget.textContent);
}
async applySuggestion(newValue) {
//newValue = null;
await this.setState({ typingChecking: "false", suggestions: [], highlightedIndex: 0 });
this.state.suggestionCallback.dispatch({
type: 'WEB_CHAT/SEND_MESSAGE',
payload: {
text: newValue
}
});
await this.setState({ typingChecking: "true" });
}
getSuggestionCss(index) {
var HIGHLIGHTED_CSS = "HIGHLIGHTED_CSS";
var SUGGESTION_CSS = "SUGGESTION_CSS";
return index === this.state.highlightedIndex ? HIGHLIGHTED_CSS : SUGGESTION_CSS;
}
handleClose(elmnt) {
var x = document.getElementsByClassName("autocomplete-items");
for (var i = 0; i < x.length; i++) {
if (elmnt !== x[i]) {
x[i].parentNode.removeChild(x[i]);
}
}
}
async componentDidMount() {
try {
await this.handleTokenGeneration();
const store =
window.WebChat.createStore(
{},
({ getState }) => next => action => {
this.state.directLine.connectionStatus$
.subscribe(connectionStatus => {
if (connectionStatus === ConnectionStatus.ExpiredToken) {
console.log("expired");
}
if (action.type === 'WEB_CHAT/SET_SEND_BOX') {
const val = action.payload.text;
if (this.state.typingChecking === "true") {
this.setState({
highlightedIndex: -1,
});
console.log(this.state.typingChecking);
this.handleSuggestion(val, store);
}
}
if (action.type === 'DIRECT_LINE/DISCONNECT_FULFILLED') {
console.log("final" + connectionStatus);
console.log("finalexpired" + ConnectionStatus.ExpiredToken);
console.log("final");
this.handleTokenGeneration();
}
});
return next(action)
}
);
this.setState({ storeValue: store });
} catch (error) {
console.log("error in fetching token");
console.log(error);
}
this.state.directLine.activity$
.filter(activity => activity.type === 'message')
.subscribe(function (activity) {
//console.log("oooooooooooooooooooooo");
}
// message => console.log("received message ", message.text)
);
}
handleSaveFeedback(ans) {
// console.log(this.state.conversationId);
// console.log(this.state.feedBack);
var userID = "C94570";
var feedbackmsg = this.state.value;
var feedbacktype = this.state.feedBack;
var convId = this.state.conversationId;
fetch('api/Feedback/SaveFeedback',
{
method: "POST",
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ Uid: userID, FeedbackMessage: feedbackmsg, Convid: convId, FeedbackType: feedbacktype })
}).
then(response => response.text())
.then(data => {
console.log(data.getResult);
});
this.setState({ value: '' });
}
feedback(ans) {
this.setState({ feedBack: ans });
if (ans === "Send") {
this.handleSaveFeedback(ans);
}
else if (ans === "Yes") {
this.setState({ popupContent: "How was your experience?" });
// console.log(this.state.value)
}
else if (ans === "No") {
this.setState({ popupContent: "What went wrong?" });
// console.log(this.state.value)
}
}
handleChange = (event) => {
this.setState({ value: event.target.value });
}
styleOptions = {
bubbleBackground: 'rgba(0, 0, 255, .1)',
bubbleFromUserBackground: 'rgba(0, 255, 0, .1)',
botAvatarInitials: 'DIA',
userAvatarInitials: 'ME'
}
render() {
if (!this.state.view) {
return
<div />
} else {
const filteredSuggestions = this.state.suggestions.filter(
suggestion =>
suggestion.toLowerCase().indexOf(this.state.suggestionTypedText.toLowerCase())
> -1
);
// console.log(this.state.view);
return (
<div className="react-container webchat" >
<div onKeyDown={this.handleKeyDown.bind(this)}>
<div >
<ReactWebChat styleOptions={this.styleOptions} directLine={this.state.directLine} webSocket={true} userID='C94570' username='Thomas' store={this.state.storeValue} sendTypingIndicator={true} />
</div>
</div>
<div className="SuggestionParent" id="Suggestion1">
{this.state.suggestions.map((suggestion, index) => (
<div className={this.getSuggestionCss(index)} key={index} onClick={this.handleSuggestionClick} >
{suggestion
.toLowerCase()
.startsWith(this.state.suggestionTypedText) ? (
<div>
<b>{this.state.suggestionTypedText}</b>
{suggestion
.toLowerCase()
.replace(this.state.suggestionTypedText, "")}
</div>
) : (
<div dangerouslySetInnerHTML={this.getSuggestionHtml(suggestion)} />
)}
</div>
))}
</div>
<footer className="chat-footer" >
<div className="foot-footer">
Was I helpful ?
<span className="feedback" onClick={() => this.feedback("Yes")} >Yes</span><span>|</span><span className="feedback" onClick={() => this.feedback("No")}>No</span>
{
this.state.feedBack === "Yes" || this.state.feedBack === "No" ?
(
<div className="dialog" id="myform">
<div id="textfeedback">
<span id="closeFeedback" onClick={() => this.feedback("Close")}>X</span>
<p>{this.state.popupContent}</p>
<input type="text" id="feedbacktxtbox" required name="textfeedback" placeholder="Pleasure to hear from u!"
onChange={this.handleChange}
value={this.state.value} />
<button type="button" id="btnfeedback" onClick={() => this.feedback("Send")}>send</button>
</div>
</div>
) : null
}
</div>
</footer>
</div>
);
}
}
}
The chat input box is called the send box in Web Chat. Clearing the send box is just setting the send box with an empty string. This is done automatically when you click on the send button normally. You can see in the submit send box saga that submitting the send box means performing two actions: sending the message and setting the send box.
if (sendBoxValue) {
yield put(sendMessage(sendBoxValue.trim(), method, { channelData }));
yield put(setSendBox(''));
}
This means that if you use the SUBMIT_SEND_BOX action then the send box will be cleared automatically. Of course, if you want that to work with your autocomplete component then you'll need to set the send box with the autocompleted text before you submit it. Your other option is to just use the SET_SEND_BOX action with an empty string after you send the message.

Return single property from object array

When I try to return a specific property from my array, the terminal say:
TypeError: Cannot read property 'url' of undefined.
I want to search a specific element that valid this button.id === this.state.currentId control. So, when it's true I want to return element.buttonColor and, in the other method I want that its return 'element.url'. Why the first method: getCurrentBackgroundColor work and the second: getCurrentImage don't work?
this.state = {
currentId: null,
buttons: [
{
id: 0,
url: "./url1.jpg",
buttonColor: "#b2d8ca"
},
{
id: 1,
url: "./url2.jpg",
buttonColor: "#fef6bb"
}
],
};
getCurrentBackgroundColor = () => {
const currentButton = this.state.buttons.find((button) => {
return button.id === this.state.currentId;
});
return currentButton === undefined ? "" : currentButton.buttonColor;
};
getCurrentImage = () => {
const currentButton = this.state.buttons.find((button) => {
return button.id === this.state.currentId;
});
return currentButton === undefined ? "" : currentButton.url;
};
render() {
return (
<div className="App">
<LeftRight
backColor={this.getCurrentBackgroundColor()}
image={this.getCurrentImage()}
/>
</div>
}
//In the LEFTRIGHT class
<div
id="left"
style={{ backgroundColor: this.props.backColor }}
key={this.props.backColor}
>
<img src={this.props.image}/>
</div>
I noticed your current id is not set, you can change 'null' in the return sentence.
this.state = {
currentId: 0,
buttons: [
{
id: 0,
url: "./url1.jpg",
buttonColor: "#b2d8ca"
},
{
id: 1,
url: "./url2.jpg",
buttonColor: "#fef6bb"
}
],
};
getCurrentBackgroundColor = () => {
const currentButton = this.state.buttons.find((button) => {
return button.id === this.state.currentId;
});
return currentButton === undefined ? "" : currentButton.buttonColor;
};
getCurrentImage = () => {
const currentButton = this.state.buttons.find((button) => {
return button.id === this.state.currentId;
});
return currentButton === undefined ? "" : currentButton.url;
};
console.log("Background: ", getCurrentBackgroundColor())
console.log("Current Image: ", getCurrentImage())
this.state = {
currentId: 1,
buttons: [{
id: 0,
url: "./url1.jpg",
buttonColor: "#b2d8ca"
},
{
id: 1,
url: "./url2.jpg",
buttonColor: "#fef6bb"
}
],
};
getCurrentBackgroundColor = () => {
this.state.buttons.map((button) => {
if (this.state.currentId === button.id) return console.log(button.buttonColor)
});
};
getCurrentBackgroundColor()

Yields "TypeError: Cannot read property 'xxxx' of undefined" after running jest with Vue

I'm trying to make a test using jest with Vue.
the details below.
Problem:
Can't mount using shallowMount option.
Situation:
Run the test after mounting the component using shallowMount option that provides in Vue-test-utils.
Throw error "Cannot read property 'XXXX' of undefined
This is my test code.
import myComponent from '#/~';
import Vuex from 'vuex';
import Vuelidate from 'vuelidate';
import { shallowMount, createLocalVue } from '#vue/test-utils';
const localVue = createLocalVue();
localVue.use(Vuex);
localVue.use(Vuelidate);
describe('myComponent~', () => {
let store;
beforeEach(() => {
store = new Vuex.Store({
modules: {
user: {
namespaced: true,
getters: {
profile: () => {
const profile = { name: 'blahblah' };
return profile;
},
},
},
},
});
});
describe('profile.name is "blahblah"', () => {
it('return something~', () => {
const wrapper = shallowMount(myComponent, {
localVue,
store,
mocks: {
$api: {
options: {
testMethod() {
return new Promise((resolve, reject) => {
resolve('test');
});
},
},
},
$i18n: {
t() {
return {
EN: 'EN',
KO: 'KO',
JP: 'JA',
SC: 'zh-CN',
TC: 'tw-CN',
};
},
},
},
});
expect(wrapper.find('.profile').text()).toBe('blahblah');
});
I think the problem is that property isn't set as a specified value or an empty value like an array or object.
But I don't know how I set properly the properties in my logic.
For example,
when the error yields "Cannot read property 'images' of undefined",
I add to a wrapper in the relevant method like this.
exampleMethod() {
this.something = this.something.map(item => {
if (item.detailContent.images) { // <-- the added wrapper is here
~~~logic~~~~
}
})
}
But the undefined properties are so many, I also think this way is not proper.
How I do solve this problem?
added
These are details about the above example method:
exampleMethod() {
this.something = this.something.map(item => {
let passValidation = false;
let failValidation = false;
if (item.detailContent.images) {
if (this.detail.showLanguages.includes(item.code)) {
if (this.configId !== 'OPTION1') {
item.detailContent.images = item.detailContent.images.map(element => {
return {
...element,
required: true,
}
});
}
checkValidationPass = true;
} else {
if (this.configId !== 'OPTION1') {
item.detailContent.images = item.detailContent.images.map(element => {
return {
...element,
required: false,
}
});
}
checkValidationPass = false;
}
return {
...item,
required: passValidation,
warning: failValidation,
}
}
});
if (this.configId === 'OPTION2') {
this.checkOption2Validation();
} else if (this.configId === 'OPTION3') {
this.checkOption3Validation();
} else {
this.checkOption1Validation();
}
},
And this is 'this.something':
data() {
return {
something: []
}
}
The detailContent is set here.
setMethod() {
this.something = [
...this.otherthings,
];
this.something = this.something.map(item => {
let details1 = {};
if (this.configId === 'OPTION2') {
details1 = {
images: [
{ deviceType: 'PC', titleList: [null, null], imageType: 'IMAGE' },
{ deviceType: 'MOBILE', titleList: [null, null, null] }
]
};
} else if (this.configId === 'OPTION3') {
details1 = {
images: [
{ deviceType: 'PC' },
{ deviceType: 'MOBILE' }
],
links: { linkType: 'EMPTY' },
};
}
let details2 = {
mainTitle: {
content: null,
}
}
let checkValidation = false;
this.detail.detailLanguages.forEach(element => {
if (element.language === item.code) {
details1 = { ...element };
if (!!element.mainTitle) {
details2 = { ...element };
} else {
details2 = {
...details2,
...element
};
}
if (this.configId !== 'OPTION1') {
details1.images = details1.images.map(image => {
return {
...image,
required: true,
}
});
}
checkValidation = true;
}
});
return {
...item,
detailContent: this.configId !== 'OPTION1' ? details1 : details2,
required: false,
warning: false,
}
});
},

How to add a value into an object which is inside map function?

I am using map function to iterate an object. but in one scenario i have to use nested map function. I try to add an value to an empty object inside an map function, but instead of adding values it replacing it. can anyone help me with this?
// object stores final results
let valid_data={}
//object to iterate
let test_cases = {
sample:
[ { test_case_no: 1,
test_case_description: 'user-status active - response 200',
value: 'active',
response_code: 200,
valid: 'yes' },
{ test_case_no: 2,
test_case_description: 'user-status inactive - response 200',
value: 'inactive',
response_code: 200,
valid: 'no' },
{ test_case_no: 3,
test_case_description: ' inappropriate user-status - response 400',
value: 'notAdmin',
response_code: 400,
valid: 'no' } ],
sample1: [ { obj1: [Array], obj2: [Array], test_case_no: 4 } ]
}
//my code to iterate an object
Object.entries(test_cases).map((property) => {
const field_name = property[0]
const field_definition = property[1]
Object.entries(field_definition).map((property) => {
if (property[1].valid != 'yes' && property[1].valid != 'no') {
Object.entries(field_definition).map((property) => {
Object.entries(property[1]).map((propertyy) => {
Object.entries(propertyy[1]).map((property) => {
nested_data = []
nested_value = {}
if (property[1].valid == 'yes') {
nested_value[propertyy[0]] = property[1].value
nested_data.push(Object.assign({}, nested_value))
valid_data[field_name] = (Object.assign({}, nested_value))
}
})
})
})
}
else if (property[1].valid == 'yes') {
valid_data[field_name] = property[1].value;
}
})
})
console.log(valid_data);
Actual result:
“{ sample: 'active',
sample1: { obj2: 2019-07-01T09:50:46.266Z } }”
Expected result:
“{ sample: 'active',
sample1: [{ obj1: 2019-07-01T09:50:46.266Z,obj2: 2019-07-01T09:50:46.266Z }] }”
Wrong var initialisation in your code.
Try this loop :
Object.entries(test_cases).map((property) => {
const field_name = property[0]
const field_definition = property[1]
Object.entries(field_definition).map((property) => {
if (property[1].valid != 'yes' && property[1].valid != 'no') {
nested_value = {}
Object.entries(property[1]).map((propertyy) => {
Object.entries(propertyy[1]).map((property) => {
if (property[1].valid == 'yes') {
nested_value[propertyy[0]] = property[1].value;
valid_data[field_name] = (Object.assign({},
nested_value))
}
})
})
} else if (property[1].valid == 'yes') {
valid_data[field_name] = property[1].value;
}
})
});
Working jsfiddle
Object.entries(test_cases).map((property) => {
const field_name = property[0]
const field_definition = property[1]
Object.entries(field_definition).map((property) => {
if (property[1].valid != 'yes' && property[1].valid != 'no') {
nested_data = []
nested_value = {}
Object.entries(property[1]).map((propertyy) => {
Object.entries(propertyy[1]).map((property) => {
if (property[1].valid == 'yes') {
nested_value[propertyy[0]] = property[1].value;
if(!nested_data.includes(nested_value)){
nested_data.push(nested_value)
valid_data[field_name] = nested_data
}
}
})
})
} else if (property[1].valid == 'yes') {
valid_data[field_name] = property[1].value;
}
})
})

Categories

Resources