I have a react native codebase in which I import a component and use the same function twice but with slight differences. I would like to outsource it into a new component somehow. Any ideas?
It looks like this :
handleConfirmApplication = async () => {
const checkVals =
get('shiftInvite.account.accountName', this.props) === ONBOARDING_ACCOUNT
? omit('payRate', this.props.confirmationCheckValues)
: this.props.confirmationCheckValues;
if (Object.values(checkVals).every(val => val)) {
this.props.onToggleConfirmPopUp();
this.props.onToggleLoadingApply();
try {
await this.handleShiftInviteDecision('ACCEPT')();
} catch (e) {
Alert.alert('Error', parseError(e));
} finally {
this.props.onToggleLoadingApply();
}
} else {
Alert.alert('Error', 'Please confirm all shift requirements');
}
};
And the second one is the following :
handleConfirmApplication = async () => {
const checkVals =
get('shift.account.accountName', this.props) === ONBOARDING_ACCOUNT
? omit('payRate', this.props.confirmationCheckValues)
: this.props.confirmationCheckValues;
if (Object.values(checkVals).every(val => val)) {
this.props.onToggleConfirmPopUp();
this.props.onToggleLoadingApply();
try {
const shiftId = this.props.shift.id;
const {
data: { updatedShifts },
} = await this.props.updateMyApplication(shiftId, 'APPLY');
this.setState({
updatedShift: updatedShifts.find(({ id }) => id === shiftId),
});
} catch (e) {
Alert.alert('Error', parseError(e));
} finally {
this.props.onToggleLoadingApply();
}
} else {
Alert.alert('Error', 'Please confirm all shift requirements');
}
};
Simply use an if/else statement in your try/catch and a ternary condition to create your string. Choosing between one or another should be done by passing a parameter to your function :
handleConfirmApplication = async (isInvite) => {
const checkVals =
get(`shift${isInvite ? 'Invite' : ''}.account.accountName`, this.props) === ONBOARDING_ACCOUNT
? omit('payRate', this.props.confirmationCheckValues)
: this.props.confirmationCheckValues;
if (Object.values(checkVals).every(val => val)) {
this.props.onToggleConfirmPopUp();
this.props.onToggleLoadingApply();
try {
if(isInvite){
await this.handleShiftInviteDecision('ACCEPT')();
}
else{
const shiftId = this.props.shift.id;
const {
data: { updatedShifts },
} = await this.props.updateMyApplication(shiftId, 'APPLY');
this.setState({
updatedShift: updatedShifts.find(({ id }) => id === shiftId),
});
}
} catch (e) {
Alert.alert('Error', parseError(e));
} finally {
this.props.onToggleLoadingApply();
}
} else {
Alert.alert('Error', 'Please confirm all shift requirements');
}
};
And calling it :
handleConfirmApplication(true)
Have I missed any other differences between your functions ?
To Use it in a reusable component :
handleConfirmApplication = async () => {
const { isInvite } = this.props
const checkVals =
And calling it :
<MyComponent isInvite={false} /> //Just switch it to true to get the other version
Related
i writen a function to convert HTML to editorState. it's work as i want but i can't use it when i assign it into the draft-wysiwyg
first function i use to call to change HTML to EditorState this function will call the other function and create EditorState on it own
function convertToEditor(markup: string): EditorState {
if (markup === '<p></p>') {
return EditorState.createEmpty()
}
const root = markupToObject(markup)
const blockContentArray: Array<ContentBlock> = []
_.forEach(root, (node, i) => {
const contentBlock = new ContentBlock({
key: genKey(),
text: node.textContent,
type: 'unstyled',
characterList: Immutable.List(getCharactorList(node.childNodes)),
data: node.getAttribute('style')?.includes('text-align') ? { 'text-align': node.getAttribute('style').split(':')[1].replace(';', '') } : {},
})
blockContentArray.push(contentBlock)
})
const contentState: ContentState = ContentState.createFromBlockArray(blockContentArray)
const editorState: EditorState = EditorState.createWithContent(contentState)
console.log(editorState)
return editorState
}
markupToObject and getCharactorList is just a function that i write to lower the complexity of the coding
function markupToObject(markup): HTMLCollection {
const div = document.createElement('div')
div.innerHTML = markup.trim()
return div.children
}
function getCharactorList(nodes: NodeListOf<ChildNode>, style?: Array<'BOLD' | 'ITALIC' | 'UNDERLINE'>): Array<CharacterMetadata> {
const characterList: Array<CharacterMetadata> = []
_.forEach(nodes, (node) => {
if (node.nodeName === '#text') {
_.forEach(node.textContent, () => {
characterList.push(CharacterMetadata.create({ style: style, entity: null }))
})
} else if (node.nodeName === 'A') {
_.forEach(node.textContent, () => {
characterList.push(CharacterMetadata.create({ style: [...(style || []), 'BOLD'], entity: null })) /* entity ID? */
})
} else {
const newStyle: Array<'BOLD' | 'ITALIC' | 'UNDERLINE'> = []
if (node.nodeName === 'STRONG') {
newStyle.push('BOLD')
} else if (node.nodeName === 'EM') {
newStyle.push('ITALIC')
} else if (node.nodeName === 'INS') {
newStyle.push('UNDERLINE')
}
characterList.push(...(getCharactorList(node.childNodes, [...newStyle, ...(style || [])]) || []))
}
})
return characterList
}
how i use
<RichText
onChange={(e) => {}}
value={convertToEditor(
'<p>text <strong>bold</strong> <strong><em>bold+italic</em></strong> </p> <p style="text-align:center;">center</p> <p><strong> link </strong></p> <p><strong> #name surname </strong></p>'
)}
/>
this is the error i got after use the Editorstate that convert from HTML
Uncaught TypeError: Cannot read properties of undefined (reading 'toList')
I want to add an All Option to my existing select box.
Select box is creating with some API data. With the API data set I want to add an ALL option above.
This is my code.
const useChemicals = () => {
const [data, setData]: any = useState([]);
useEffect(() => {
const getChemicalsData = async () => {
try {
const results = await searchApi.requestChemicalsList();
if (results.data) {
let groupCount = 0;
const chemList: any = [];
results.data.data.chemicals.map((chemical: any, index: number) => {
if (chemical.key === '') {
chemList.push({
label: chemical.value,
options: [],
});
}
});
results.data.data.chemicals.map((chemical: any, index: number) => {
if (chemical.key === '') {
if (index > 1) {
groupCount += 1;
}
} else {
chemList[groupCount].options.push({
label: chemical.value,
value: chemical.key,
});
}
});
setData([...chemList]);
}
} catch (e) {}
};
getChemicalsData();
}, []);
return data && data;
};
export default useChemicals;
How can I add this. Please help me, I am new to React.
I have a function that updates a state with a change and adds a value, but the state in the 'addResponse' function does not always change:
handleSelected (e, item) {
this.setState({
current_component_id: item.id,
}, () => this.addResponse()
);
};
Call function above:
addResponse (e) {
const { enrollment_id, evaluation_id, user_id, question_id, current_component_id,
responses, current_question, current_question_id
} = this.state;
console.log(current_component_id)
if (current_component_id != 0) {
const newResponse = {
enrollment_id: enrollment_id,
evaluation_id: evaluation_id,
user_id: user_id,
question_id: current_question_id,
answer_component: current_component_id,
};
function hasAnswer(res) {
const list_question_id = res.map((item) => {
return item.question_id
});
if (list_question_id.includes(current_question_id)) {
return true
} else {
return false
}
}
if (responses === undefined) {
this.setState({
responses: [newResponse]
}
, () => console.log('---------> primeiro', this.state.responses)
)
} else {
const check = hasAnswer(responses);
if (check) {
this.setState(prevState => {
prevState.responses.map((item, j) => {
if (item.question_id === current_question_id) {
return item.answer_component = current_component_id
}
return item ;
})
}
, () => { console.log('----> questao alterada ', this.state.responses)}
)
} else {
this.setState({
responses: [...this.state.responses, newResponse]
}
, () => console.log('------> questao nova', this.state.responses)
);
}
}
}
// this.nextQuestion();
};
the first console.log is always correct, but the others do not always change, I know that setState is asyn, but I thought that as I call the addResponse function it would be async
There is a problem in your how you call setState when check is true.
It should be
this.setState(prevState => ({
responses: prevState.responses.map((item, j) => {
if (item.question_id === current_question_id) {
item.answer_component = current_component_id
}
return item ;
})
})
, () => { console.log('----> questao alterada ', this.state.responses)}
)
So, I have this component
<ConfirmApplicationPopUp
onConfirm={() => handleConfirmApplication(true)}
/>
whenever i try to run the function[it's passed to the props of ConfirmApplicationPopUp component as you can see] it tells me that it's undefined
my function is in another file
I import it like this
import handleConfirmApplication from '../shift-details/utils';
the function itself is
export const handleConfirmApplication = async (isInvite) => {
const checkVals =
get(`shift${isInvite ? 'Invite' : ''}.account.accountName`, this.props) === ONBOARDING_ACCOUNT
? omit('payRate', this.props.confirmationCheckValues)
: this.props.confirmationCheckValues;
if (Object.values(checkVals).every(val => val)) {
this.props.onToggleConfirmPopUp();
this.props.onToggleLoadingApply();
try {
if(isInvite) {
await this.handleShiftInviteDecision('ACCEPT')();
}
else {
const shiftId = this.props.shift.id;
const {
data: { updatedShifts },
} = await this.props.updateMyApplication(shiftId, 'APPLY');
this.setState({
updatedShift: updatedShifts.find(({ id }) => id === shiftId),
});
}
} catch (e) {
Alert.alert('Error', parseError(e));
} finally {
this.props.onToggleLoadingApply();
}
} else {
Alert.alert('Error', 'Please confirm all shift requirements');
}
}
Any ideeas why that happens? I have checked some of the other topics about this but with no avail :(
It's because you are not exporting the function as default.
If you import it in the following way it should work.
import { handleConfirmApplication } from '../shift-details/utils';
So, I have this component,
{ this.props.isConfirmModalOpen && shiftInvite && <ConfirmApplicationPopUp
memberPhoto={props.memberProfile && props.memberProfile.photo}
venueLogo={getOr('noop', 'account.logo', shiftInvite)}
isOpen={props.isConfirmModalOpen}
shift={shiftInvite}
isOnboarding={isOnboardingMember}
onClose={props.onToggleConfirmPopUp}
onConfirm={this.handleConfirmApplication}
checkValues={props.confirmationCheckValues}
onUpdateCheckValues={props.onUpdateConfirmationCheckValues}
isHomeComponent
/> }
As you can see, I pass on onConfirm the handleConfirmApplication function, which is a check for some stuff and has to run a function in the try block, , here's the function
handleConfirmApplication = async () => {
const checkVals =
get('shift.account.accountName', this.props) === ONBOARDING_ACCOUNT
? omit('payRate', this.props.confirmationCheckValues)
: this.props.confirmationCheckValues;
if (Object.values(checkVals).every(val => val)) {
this.props.onToggleConfirmPopUp();
this.props.onToggleLoadingApply();
try {
console.log('inTry1');
await this.handleShiftInviteDecision('ACCEPT');
console.log('inTry2');
} catch (e) {
Alert.alert('Error', parseError(e));
} finally {
this.props.onToggleLoadingApply();
console.log('inFinally');
}
} else {
Alert.alert('Error', 'Please confirm all shift requirements');
}
};
My problem is, for whatever reason, it doesn't run the handleShiftInviteDecision('ACCEPT) for whatever reason, i'm awaiting it, tried to put it in another function, call them both from another function ETC, the function does not run!
Here's the handleShiftInviteDecision function too
handleShiftInviteDecision = (decision: 'ACCEPT' | 'DECLINE') => async () => {
console.log('handleSIDecision1');
const [shiftInvite] = getOr([], 'shiftInvites', this.state.modals);
console.log('handleSIDecision2');
if (decision === 'ACCEPT') {
analytics.hit(new PageHit(`ShiftInviteModal-ACCEPT-${shiftInvite.id}`));
console.log('handleSIDecision3');
} else if (decision === 'DECLINE') {
analytics.hit(new PageHit(`ShiftInviteModal-DECLINE-${shiftInvite.id}`));
console.log('handleSIDecision4');
}
try {
console.log("thisSHouldRun")
this.setState({ isLoading: true, display: false });
await this.props.updateMyApplication(shiftInvite.id, decision);
console.log('handleSIDecision5');
} catch (e) {
Alert.alert('Error', parseError(e));
} finally {
this.setState({ isLoading: false, display: false });
}
};
Any ideeas on what I could do?
The function handleShiftInviteDecision is a function that returns an async function.
handleShiftInviteDecision = (decision: 'ACCEPT' | 'DECLINE') => async () => {
So, you would need to call the async function it returns to invoke it:
try {
console.log('inTry1');
await this.handleShiftInviteDecision('ACCEPT')(); // <--- here
console.log('inTry2');
} catch (e) {