I have a React component which is trying to render another component that has function inside it as a child. When I try to render that component it returns an [Object]. I am trying to find another way to render that child component.
Right now, I tried to render it with React.createElement(), yet it also returned an object. I am using react-beautiful-dnd library to use Drag and Drop feature. This library has Droppable component and it takes a function inside which has two parameters, provided, snapshot.
Since it takes a function, when I try to render Droppable component, it returns an object instead of react element.
DroppableContent.js
const DroppableContent = ({ droppedBlank, label, id }) => (
<Droppable droppableId={id || _.uniqueId('droppable_')}>
{(provided, snapshot) => (
<span ref={provided.innerRef} style={{ display: 'inline' }} {...provided.droppableProps}>
{/* blank placeholder */}
<span className={droppedBlank ? styles.dropped : styles.placeholder}
style={{ backgroundColor: !droppedBlank && snapshot.isDraggingOver ? '#88d2ee' : '#fff' }}
>
{droppedBlank ? <BlankItem label={label} index={id} /> : null}
</span>
</span>
)}
</Droppable>
);
DragAndDrop.js where I call QuestionPreview component.
import React from 'react';
import PropTypes from 'prop-types';
import { withTranslation } from 'react-i18next';
import { DragDropContext, Droppable } from 'react-beautiful-dnd';
import _ from 'lodash';
import * as questionStyles from '../Questions.less';
import BlankList from './BlankList';
import BlankItem from './BlankItem';
import QuestionPreview from './QuestionPreview';
const DragAndDrop = ({
question, onAnswer, answer, hideTitle, className, t, readOnly,
}) => {
const handleDragEnd = (result) => {
const { destination, source, draggableId } = result;
if (!destination) {
return;
}
if (destination.droppableId === source.droppableId && destination.index === source.index) {
return;
}
const destinationId = destination.droppableId;
const sourceId = draggableId;
const blank = {
textIndex: destinationId,
id: sourceId,
// answer: _.find(questionBlanks, b => b.id === sourceId).answer,
};
let updatedBlanks;
if (destinationId === 'answerBlanks') {
updatedBlanks = _.filter(answer.blanks, item => item.id !== blank.id);
} else {
updatedBlanks = _.filter(answer.blanks, item => item.textIndex !== blank.textIndex);
updatedBlanks.push(blank);
}
onAnswer(question, { blanks: updatedBlanks });
};
const blankLabels = currentLabels => _.filter(currentLabels, l => !_.includes(_.map(answer.blanks, ab => ab.id), l.id)).map((label, index) => (
<BlankItem key={label.id} label={label} index={index} />
));
const blankItems = currentBlanks => _.map(currentBlanks, (currentBlank, index) => (
<BlankItem key={currentBlank.id} label={currentBlank} index={index} readOnly />
));
const { text } = question;
const shuffledLabels = question.labels && _.shuffle(question.labels);
// filtering answers from blank items so that whenever we drag an item to a blank,
// answer will be removed.
const filteredLabels = shuffledLabels && blankLabels(shuffledLabels);
const filteredBlanks = blankItems(question.blanks);
return (
<DragDropContext onDragEnd={handleDragEnd}>
<div>
<p style={{ fontWeight: 600 }}>
{t('defaultDndText', { numberOfBlanks: question.blanks.length })}
</p>
<Droppable droppableId="answerBlanks">
{provided => (
<div>
<BlankList innerRef={provided.innerRef} {...provided.droppableProps}>
{readOnly ? filteredBlanks : filteredLabels}
</BlankList>
</div>
)}
</Droppable>
{!hideTitle && (
<QuestionPreview blanks={_.filter(question.blanks, blank => blank.textIndex < 100)}
labels={question.labels}
selectedBlanks={answer.blanks}
text={text}
className={[questionStyles.title, className].join(' ')}
/>
)}
</div>
</DragDropContext>
);
};
DragAndDrop.propTypes = {
question: PropTypes.shape({
text: PropTypes.string,
}).isRequired,
answer: PropTypes.shape({
blanks: PropTypes.arrayOf(PropTypes.shape({})),
}),
readOnly: PropTypes.bool,
disabled: PropTypes.bool,
hideTitle: PropTypes.bool,
onAnswer: PropTypes.func,
className: PropTypes.string,
};
DragAndDrop.defaultProps = {
onAnswer: () => {},
disabled: false,
hideTitle: false,
className: '',
answer: { blanks: [] },
readOnly: false,
};
export default withTranslation('question')(DragAndDrop);
QuestionPreview.js where I try to render DroppableContent component.
const QuestionPreview = ({
text, labels, selectedBlanks, readOnly,
}) => {
const readOnlyContent = (id) => {
const droppedBlank = selectedBlanks && _.find(selectedBlanks, blank => blank.textIndex === id);
const label = droppedBlank && _.find(labels, l => l.id === droppedBlank.id);
return (
<span className={droppedBlank ? styles.dropped : styles.placeholder}>
{droppedBlank && <BlankItem label={label} readOnly />}
</span>
);
};
const splittedText = splitTextWithBlanks(text);
const blankIndices = getBlankIndices(text);
const getContentId = index => blankIndices[index];
const tempArray = [];
const html = () => {
_.map(splittedText, (element, index) => {
const contentId = getContentId(index);
const droppedBlank = selectedBlanks && _.find(selectedBlanks, blank => blank.textIndex === contentId);
const label = droppedBlank && _.find(labels, l => l.id === droppedBlank.id);
const blankContent = readOnly ? readOnlyContent(contentId) : <DroppableContent id={contentId} droppedBlank={droppedBlank} label={label} />;
const htmlContent = <span dangerouslySetInnerHTML={{ __html: toHTML(element) }} />;
tempArray.push(htmlContent);
if (index !== splittedText.length - 1) {
tempArray[index] = tempArray[index] + blankContent;
}
});
return tempArray;
};
const createdElement = React.createElement('div', null, html());
return createdElement;
};
This does not return any error but what I want to achieve is that combining htmlContent variable with blankContent. When I do that, it does render blankContent as an Object. In the end, I just want to find a way to parse Droppable component.
You might have error in the following line
const blankContent = readOnly ? readOnlyContent : <DroppableContent id={contentId} droppedBlank={droppedBlank} label={label} />;
You are passing reference of readOnlyContent, May be you want to call
readOnlyContent (contentId) .BTW your code is complex and hard to maintain/read. try to refactor it
Edit 1 Try this QuestionPreview.js
const QuestionPreview = ({
text, labels, selectedBlanks, readOnly,
}) => {
const readOnlyContent = (id) => {
const droppedBlank = selectedBlanks && _.find(selectedBlanks, blank =>
blank.textIndex === id);
const label = droppedBlank && _.find(labels, l => l.id ===
droppedBlank.id);
return (
<span className={droppedBlank ? styles.dropped : styles.placeholder}>
{droppedBlank && <BlankItem label={label} readOnly />}
</span>
);
};
const splittedText = splitTextWithBlanks(text);
const blankIndices = getBlankIndices(text);
const getContentId = index => blankIndices[index];
const tempArray = [];
const html = () => {
return _.map(splittedText, (element, index) => {
const contentId = getContentId(index);
const droppedBlank = selectedBlanks && _.find(selectedBlanks, blank =>
blank.textIndex === contentId);
const label = droppedBlank && _.find(labels, l => l.id ===
droppedBlank.id);
const blankContent = readOnly ? readOnlyContent(contentId) :
<DroppableContent id={contentId} droppedBlank={droppedBlank} label=
{label}
/>;
let htmlContent = <span dangerouslySetInnerHTML={{ __html:
toHTML(element) }} />;
if (index !== splittedText.length - 1) {
return (
<Fragment>
{htmlContent}
{blankContent}
</Fragment>
)
}
return htmlContent
});
};
return (
{html()}
)
};
Related
I'm trying to convert an an app from javascript to typescript and I'm having issues. I'm new to typescript and Jotai. I'm getting the error in the Attribute function on attribute?placement. It's like it doesn't recognize that it is an array of strings. Can someone please help me decipher what I'm doing wrong.
import { splitAtom } from "jotai/utils";
import { focusAtom } from 'jotai-optics';
import { atom, useAtom, useAtomValue } from "jotai";
import cat from '../cat.json';
import { Key, useMemo } from "react";
import { Switch } from "#chakra-ui/react";
const catAtom = atom(cat);
const partsAtom = focusAtom(catAtom, (optic) => optic.prop("parts"));
const partsAtomAtoms = splitAtom(partsAtom);
const useAttributesAtom = (partAtom:any) => {
return useMemo(
() => focusAtom(partAtom, (optic:any) => optic.prop("attributes")),
[partAtom]
);
};
const useAttributeAtom = (attributesAtom:any, index:number) => {
// const { attributesAtom, index } = props;
return useMemo(() => {
return focusAtom(attributesAtom, (optic) => optic.at(index));
}, [attributesAtom, index]);
};
const Attribute = (attributesAtom:any, index:number) => {
// const { attributesAtom, index } = props;
const attributeAtom = useAttributeAtom(attributesAtom, index);
const [attribute, setAttribute] = useAtom(attributeAtom);
return (
<div style={{ display: "flex" }}>
<label>
<span style={{ marginRight: "16px" }}>{attribute?.placement}</span>
<Switch
onChange={(checked) =>
setAttribute((prevAttribute: any) => ({
...prevAttribute,
injured: checked
}))
}
checked={attribute?.injured}
/>
</label>
</div>
);
};
const Part = (partAtom:any) => {
const [part] = useAtom(partAtom) as typeof partAtom;
const attributesAtom = useAttributesAtom(partAtom);
const attributes = useAtomValue(attributesAtom) as typeof partAtom;
return (
<div>
<h3>{part.type}</h3>
{attributes.map((attribute: { placement: Key | null | undefined; }, index:
number) => {
return (
<Attribute
key={attribute.placement}
attributesAtom={attributesAtom}
index={index}
/>
);
})}
</div>
);
};
const PetParts = () => {
const [partsAtoms] = useAtom(partsAtomAtoms);
return (
<div>
<h2>Body Injury Details</h2>
{partsAtoms.map((partAtom) => {
return <Part key={`${partAtom}`} partAtom={partAtom} />;
})}
</div>
);
};
export default PetParts;
I have the following functional component that takes in some data and render a line chart. However depending on the type of data I would like to change the type of chart being used, i.e. (Line, Bar, etc).
As such I have a main component FieldCompareChart. This component determines what type of chart should be displayed based on the data graphs prop and determines if the yAxis should be on the left or right. It then renders the ResponsiveContainer and calls BuildYaxis as shown below.
I have the yAxis types is separate files as function components that return the type of chart being used.
Having it this way does not render the lines in the graph.
However if I pass the contents of dbVhChart directly into the return statement of the if clause of the BuildYAxis function, this works. I am trying to understand why importing doesn't but the other does.
import React from "react";
import {
LineChart,
XAxis,
CartesianGrid,
Legend,
ResponsiveContainer,
ReferenceArea,
YAxis,
Line,
} from "recharts";
import axisConfigs from "./yAxisConfig.json";
import DbVhChart from "./yAxisTypes/dbVh";
import DbVvChart from "./yAxisTypes/dbVv";
import NdviChart from "./yAxisTypes/ndvi";
function BuildYaxis(props) {
const { data, graphs, activeCrop, hideCrops } = props;
return Object.keys(data[0])
.filter((n) => ["date", "timestamp"].indexOf(n) === -1)
.map((c, index) => {
const sub = c.split("_").pop();
const idx = graphs.findIndex((val) => val === sub);
const chartProps = {
idx,
axisConfig: axisConfigs[sub],
activeCrop,
hideCrops,
dataKey: c,
};
if (sub === "dbVv") {
return <DbVvChart key={`dbVv-${index}`} {...chartProps} />;
}
return null;
});
}
const FieldCompareChart = (props) => {
const {
data,
activeCrop,
setActiveCrop,
hideCrops,
toggleCrop,
syncId,
showLegend,
left,
right,
refAreaLeft,
refAreaRight,
setRefAreaLeft,
setRefAreaRight,
zoom,
zoomOut,
graphs,
top,
bottom,
top2,
bottom2,
} = props;
if (data && data.length) {
return (
<div
className="highlight-bar-charts"
style={{ userSelect: "none", height: "calc(100vh - 100px)" }}
>
<button type="button" className="btn update" onClick={zoomOut}>
Zoom Out
</button>
<ResponsiveContainer width="100%" height="92%">
<LineChart
data={data}
onMouseLeave={() => setActiveCrop(null)}
onMouseDown={(e) => {
// this prevents an error from being thrown when the legend is clicked in the graphs
if (!e) return;
setRefAreaLeft(e);
}}
onMouseMove={(e) => {
if (!e) return;
refAreaLeft && setRefAreaRight(e);
}}
// eslint-disable-next-line react/jsx-no-bind
onMouseUp={(e) => {
// this prevents an error from being thrown when the legend is clicked in the graphs
if (!e) return;
if (!refAreaRight) {
return setRefAreaLeft("");
}
zoom();
}}
syncId={syncId}
width={500}
height={300}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5,
}}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis
domain={[left, right]}
allowDataOverflow
dataKey="date"
type="category"
tickFormatter={(a) => {
if (a === "auto") {
return a;
}
return new Date(a).toLocaleDateString();
}}
/>
{Object.keys(data[0])
.filter((n) => ["date", "timestamp"].indexOf(n) === -1)
.map((c, index) => {
const sub = c.split("_").pop();
const idx = graphs.findIndex((val) => val === sub);
return (
<YAxis
key={`yAxis-key-${index}`}
allowDataOverflow
domain={idx === 0 ? [bottom, top] : [bottom2, top2]}
type="number"
yAxisId={idx}
tickFormatter={(a) => parseFloat(a).toFixed(1)}
orientation={idx === 0 ? "left" : "right"}
/>
);
})}
{showLegend && (
<Legend
onClick={toggleCrop}
onMouseOver={(e) => setActiveCrop(e.dataKey)}
/>
)}
{BuildYaxis({ data, graphs, activeCrop, hideCrops })}
{refAreaLeft && refAreaRight ? (
<ReferenceArea
yAxisId="1"
x1={refAreaLeft}
x2={refAreaRight}
strokeOpacity={0.3}
/>
) : null}
</LineChart>
</ResponsiveContainer>
</div>
);
}
return null;
};
export default FieldCompareChart;
import React from "react";
import { Line } from "recharts";
import randomcolor from "randomcolor";
function DbVhChart(props) {
console.log(props);
const { idx, axisConfig, activeCrop, hideCrops, dataKey } = props;
return (
<Line
key={`comparison-chart-${dataKey}`}
yAxisId={idx}
type="natural"
animationDuration={300}
connectNulls
strokeDasharray={""}
dataKey={dataKey}
strokeWidth={activeCrop === null ? 1 : activeCrop === dataKey ? 3 : 1}
stroke={randomcolor({
luminosity: "bright",
seed: axisConfig.seed,
format: "rgba",
alpha: activeCrop === null || activeCrop === dataKey ? 1 : 0.2,
})}
hide={hideCrops.indexOf(dataKey) >= 0}
/>
);
}
export default DbVhChart;
Not working
...
function BuildYaxis(props) {
const { data, graphs, activeCrop, hideCrops } = props;
return Object.keys(data[0])
.filter((n) => ["date", "timestamp"].indexOf(n) === -1)
.map((c, index) => {
const sub = c.split("_").pop();
const idx = graphs.findIndex((val) => val === sub);
const chartProps = {
idx,
axisConfig: axisConfigs[sub],
activeCrop,
hideCrops,
dataKey: c,
};
console.log(`dbVv-${index}`);
if (sub === "dbVv") {
return <DbVvChart key={`dbVv-${index}`} {...chartProps} />;
}
return null;
});
}
...
Working:
...
function BuildYaxis(props) {
const { data, graphs, activeCrop, hideCrops } = props;
return Object.keys(data[0])
.filter((n) => ["date", "timestamp"].indexOf(n) === -1)
.map((c, index) => {
const sub = c.split("_").pop();
const idx = graphs.findIndex((val) => val === sub);
const chartProps = {
idx,
axisConfig: axisConfigs[sub],
activeCrop,
hideCrops,
dataKey: c,
};
if (sub === "dbVv") {
return (
<Line
key={`comparison-chart-${c}`}
yAxisId={idx}
type="natural"
animationDuration={300}
connectNulls
strokeDasharray={""}
dataKey={c}
strokeWidth={activeCrop === null ? 1 : activeCrop === c ? 3 : 1}
stroke={randomcolor({
luminosity: "bright",
seed: axisConfigs[sub].seed,
format: "rgba",
alpha: activeCrop === null || activeCrop === c ? 1 : 0.2,
})}
hide={hideCrops.indexOf(c) >= 0}
/>
);
}
return null;
});
}
...
I'm using function component to create a MUI dataGrid, and trying to add a button in a column, and I have a onRowClick function to open a side pane when user clicking row. The problem is, once I click row, react will report error:
Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
Here is the code:
const openViewPane = (params: GridRowParams, e): void => {
setRightSlidePlaneContent(
<ViewAccountPane
close={closeForm}
params={params}
/>,
);
setRightSlidePlaneOpen(true);
};
const formatDates = (columns): GridColDef[] => {
return columns;
};
const addTooltipsToData = (columns: GridColDef[]): GridColDef[] => {
console.log('render tool bar called');
return columns.map((column) => {
const { description, field, headerName } = column;
console.log('inside map');
if (field === ID) {
console.log('直接return');
return column;
}
return {
...column,
renderCell: (): JSX.Element => {
console.log('render run');
return (
<Tooltip arrow title={description || ''} >
<span className={classes.headerCell}>{headerName}</span>
</Tooltip>
);
},
};
});
};
const formatColumns = (columns: GridColDef[]): GridColDef[] => {
const dateFormatted = formatDates(columns);
return addTooltipsToData(dateFormatted);
};
console.log('generic table rendered');
return (
<MuiThemeProvider theme={theme}>
<DataGrid
columns={formatColumns(columns)}
rows={rows}
autoHeight
className={classes.table}
components={{
Toolbar: CustomToolbar,
}}
density={GridDensityTypes.Compact}
filterMode={tableMode}
hideFooterSelectedRowCount
loading={loading}
onFilterModelChange={handleFilterChange}
onSortModelChange={handleSortChange}
sortModel={sortModel}
sortingMode={tableMode}
onRowClick={openViewPane}
/>
</MuiThemeProvider>
);
However, if I change the renderCell to renderHeader, it will work fine.
setRightSlidePlaneContent
setRightSlidePlaneOpen
Above are two state passed by parent component in props. it will open a slide pane.
After I comment setRightSliePlaneOpen, it will work well. But no slide pane show.
Please help me slove it. Or do you know how can I add a button in column not using renderCell?
const PageFrame: FC<IProps> = (props: IProps) => {
const classes = useStyles();
const dispatch = useAppDispatch();
const { Component, userInfo } = props;
const [navBarOpen, setNavBarOpen] = useState(false);
const [rightSlidePlaneOpen, setRightSlidePlaneOpen] = useState(false);
const [rightSlidePlaneContent, setRightSlidePlaneContent] = useState(
<Fragment></Fragment>,
);
const [rightSlidePlaneWidthLarge, setRightSlidePlaneWidthLarge] = useState(
false,
);
useEffect(() => {
dispatch({
type: `${GET_USER_LOGIN_INFO}_${REQUEST}`,
payload: {
empId: userInfo.empId,
auth: { domain: 'GENERAL_USER', actionType: 'GENERAL_USER', action: 'VIEW', empId: userInfo.empId},
},
meta: { remote: true },
});
}, []);
return (
<div className={classes.root}>
<HeaderBar
navBarOpen={navBarOpen}
toggleNavBarOpen={setNavBarOpen}
/>
<NavigationBar open={navBarOpen} toggleOpen={setNavBarOpen} />
<Component
setRightSlidePlaneContent={setRightSlidePlaneContent}
setRightSlidePlaneOpen={setRightSlidePlaneOpen}
setRightSlidePlaneWidthLarge={setRightSlidePlaneWidthLarge}
/>
<PersistentDrawerRight
content={rightSlidePlaneContent}
open={rightSlidePlaneOpen}
rspLarge={rightSlidePlaneWidthLarge}
/>
</div>
);
};
export default PageFrame;
The component that calls setRightSidePlaneOpen
interface IProps {
setRightSlidePlaneContent: React.Dispatch<React.SetStateAction<JSX.Element>>;
setRightSlidePlaneOpen: React.Dispatch<React.SetStateAction<boolean>>;
setRightSlidePlaneWidthLarge: React.Dispatch<SetStateAction<boolean>>;
}
const TagDashboard = (props: IProps): JSX.Element => {
const { setRightSlidePlaneContent, setRightSlidePlaneOpen, setRightSlidePlaneWidthLarge } = props;
const employeeId = useAppSelector((store) => store.userInfo.info.employeeNumber);
const rows = useAppSelector((state) => state.tag.rows);
const accountId = useAppSelector(store => store.userInfo.accountId);
const updateContent = useAppSelector(state => state.tag.updateContent);
const numOfUpdates = useAppSelector(state => state.tag.numOfUpdates);
const dispatch = useAppDispatch();
const closeAddForm = (): void => {
setRightSlidePlaneContent(<Fragment />);
setRightSlidePlaneOpen(false);
};
const openAddForm = (): void => {
setRightSlidePlaneContent(
<AddForm
category={'tag'}
close={closeAddForm}
title={ADD_FORM_TITLE}
createFunction={createTag}
/>);
setRightSlidePlaneOpen(true);
};
const closeForm = (): void => {
setRightSlidePlaneContent(<Fragment />);
setRightSlidePlaneOpen(false);
setRightSlidePlaneWidthLarge(false);
};
const openViewPane = (params: GridRowParams, e): void => {
setRightSlidePlaneContent(
<ViewAccountPane
close={closeForm}
params={params}
/>,
);
setRightSlidePlaneOpen(true);
setRightSlidePlaneWidthLarge(true);
};
// to the RSP.
return (
<GenericDashboard
addFunction={openAddForm}
description={DESCRIPTION}
title={TITLE}
columns={columns}
handleRowClick={openViewPane}
rows={rows}
numOfUpdates={numOfUpdates}
updateContent={updateContent}
/>
);
};
This is the component of the right slide pane
const { content, open, rspLarge } = props;
const classes = useStyles();
const drawerClass = rspLarge ? classes.drawerLarge : classes.drawer;
const drawerPaperClass = rspLarge ? classes.drawerPaperLarge : classes.drawerPaper;
return (
<div className={classes.root}>
<CssBaseline />
<Drawer
className={drawerClass}
variant='temporary'
anchor='right'
open={open}
classes={{
paper: drawerPaperClass,
}}
>
<Fragment>{content}</Fragment>
</Drawer>
</div>
);
import React, { useState, useEffect, Fragment } from "react";
import Button from "../../../Resources/Forms/Button";
import Switch from "../../../Resources/Forms/Switch";
import { POST } from "../../../Utils/api";
import Radio from "../../../Resources/Forms/Radio";
import withAppData from "../../../HOC/withAppData";
const InventorySettings = (props) => {
const [state, setState] = useState({});
const [isSaving, setIsSaving] = useState();
const [isStockRequestChecked, setIsStockRequestChecked] = useState(false);
const getStatus = id => {
return props.context.isSettingsActivated(id) ? 1 : 0;
};
const setBusinessSettings = async () => {
const defaultSettings = [
{ state: "enableStockRequest", id: 53 },
{ state: "connectWarehousePickStock", id: 52 },
{ state: "approveRequestOtp", id: 51 },
{ state: "approveRequestManually", id: 50 }
];
for (const setting of defaultSettings) {
await setState({ [setting.state]: getStatus(setting.id) });
}
};
function chooseApprovalMethod(methodType) {
const currentValue = state[methodType];
setState({[methodType]
: currentValue === 1 ? 0: 1})
}
async function saveApprovalMethod() {
setIsSaving(true)
const approvalSettings = [{text:"approvalRequestManually", id: 51}, {text:"approveRequestOtp", id: 50}]
for(const el of approvalSettings) {
const currentValue = state[el.text];
const data = {
settingId: el.id,
status: currentValue
}
await POST(`Common/AddBusinessSetting`, data);
}
setIsSaving(false);
props.context.getBusinessSettings();
}
const updateBasicSettings = async (id, key) => {
setState({ [key]: !state[key] ? 1 : 0 });
const data = {
SettingId: id,
Status: state[key],
};
await POST(`Common/AddBusinessSetting`, data);
props.context.getBusinessSettings();
};
useEffect(() => {
setBusinessSettings();
}, []);
return (
<Fragment>
<div className="basic-settings-section">
<Switch
label={"Connect Warehouse Stock to pick stock"}
light={true}
checked={state && state.connectWarehousePickStock === 1}
onChange={() => updateBasicSettings(52, "connectWarehousePickStock")}
></Switch>
</div>
<div className="basic-settings-section">
<Switch
label={"Stock Request"}
light={true}
checked={isStockRequestChecked}
onChange={() => setIsStockRequestChecked(!isStockRequestChecked)}
></Switch>
{isStockRequestChecked && (
<div className="basic-settings-plan-generate">
<div
className="form__label"
style={{ padding: "2px", marginBottom: "20px" }}
>
<p>Please choose an approval method</p>
</div>
<Radio
label={"Manual Approval"}
name="approval"
value="50"
id="50"
checked={state && state.approveRequestManually === 1}
// onChange={() => (chooseApprovalMethod)}
/>
<Radio
label={"OTP Approval"}
name="approval"
value="51"
id="51"
checked={state && state.approveRequestOtp === 1}
// onChange={() => (chooseApprovalMethod)}
/>
<div className="password-settings-btn"
// onClick={props.context.showToast}
>
<Button
type={"outline"}
size={"medium"}
text={"Save"}
disabled={!state.approveRequestOtp && !state.approveRequestManually}
withMargin={false}
loading={isSaving}
onClick={saveApprovalMethod}
></Button>
</div>
</div>
)}
</div>
</Fragment>
);
}
export default withAppData(InventorySettings);
I added the chooseApprovalMethod function to the radio buttons but still I wasn't getting it well. So I had to call there state using state.text is equal to 1. Please help me out I don't think I know what I'm doing anymore.
Please above are my code, the radio buttons aren't checking or highlighting, so I want them to be checked when clicked on, and I want there ids to be saved when clicking on the save button.
So please guys help me out, as I don't understand it anymore.
how I can update price value when update quantity value automatically ??
page design
interface ui
print values on the console:
print values on the console:
This sentence needs to be modified
{quantity[initQ] == 1 ? data.price : initP[initQ]}
i use setState to save multiple values
export default function Contaner({ setPressed, getPressed }) {
const [products, setProducts] = useState([]);
const [layout, setLayout] = useState('list');
let initQ = 1;
const [initP,setInitP] = useState({ [initQ]: 1 }) ;
const [quantity, setQuantity] = useState({ [initQ]: 1 });
function checkQuantity(e, data) {
if (e.value <= data.quantity) {
initQ = data.name;
setQuantity({ ...quantity, [data.name]: e.value});
setInitP( { ...quantity, [data.name]: data.price * e.value});
console.log(initP );
setCart(current => [...current, data.name]);
}
else {
showError();
}
}
const renderListItem = (data) => {
return (
<div style={{ display: "flex" }}>
<button className="button_color" onClick={() => removeItem(data)}>
<i className="pi pi-trash"></i>
</button>
<h6>{quantity[initQ] == 1 ? data.price : initP[initQ] }</h6>
<InputNumber id="stacked" showButtons min={1} value={quantity[initQ]}
onValueChange={(e) => checkQuantity(e, data)} />
<InputText disabled={true} value={"₪ " + data.price} />
<h6>{data.name}</h6>
</div>
);
}
const itemTemplate = (product, layout) => {
if (!product) {
return <></>;
}
if (layout === 'list') {
return renderListItem(product);
}
}
return(
<DataView value={products} layout={layout} itemTemplate={itemTemplate} rows={1} />
);
}