Reactjs 基于公式的动态计算平方英尺
我正在使用React/Formik/Yup和Node/expressapi+Postgres数据库构建一个应用程序。该应用程序的一个功能要求根据包装样式和相关公式计算一个盒子/其他纸板包装的平方英尺。例如,“RSC”样式框的公式为Reactjs 基于公式的动态计算平方英尺,reactjs,eval,formik,yup,Reactjs,Eval,Formik,Yup,我正在使用React/Formik/Yup和Node/expressapi+Postgres数据库构建一个应用程序。该应用程序的一个功能要求根据包装样式和相关公式计算一个盒子/其他纸板包装的平方英尺。例如,“RSC”样式框的公式为((长*2+宽*2+x1)*(高*2))/144。这两者都作为字符串存储在数据库中的对象中 我当前的解决方案可以运行,但如果用户遗漏了必填字段,应用程序就会崩溃。 我遇到的问题是,不同设计的必填字段会发生变化 import React, { useState, useE
((长*2+宽*2+x1)*(高*2))/144
。这两者都作为字符串存储在数据库中的对象中
我当前的解决方案可以运行,但如果用户遗漏了必填字段,应用程序就会崩溃。
我遇到的问题是,不同设计的必填字段会发生变化
import React, { useState, useEffect } from 'react';
// importing axios for http requests
import axios from 'axios';
// Formik/yup (form validation library) import
import { withFormik, Form, Field } from 'formik'
import * as yup from 'yup';
// styling imports
import './BoxCalculator.scss';
const BoxCalculator = ({ values, touched, errors }) => {
//useState hook to store options we dynamically render in the <select> tag
const [ boxStyles, setBoxStyles ] = useState();
// pulling the list of possible box formulas from the API on page render, going to save it to an array
useEffect(() => {
axios.get('http://localhost:5000/api/box-styles')
.then(res => {
setBoxStyles(res.data.data);
console.log(boxStyles);
})
.catch(err => {
console.log(err);
});
// this next line eliminates the linter error causes by having an empty dependency array
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
const calculateFootage = () => {
// selecting the Box Style the user has selected
const style = document.getElementById('style').value;
// filtering the array to find the box_style_formula based on the
let styleFormulaArr = boxStyles.filter(box => box.box_style_name === style)
let formula = styleFormulaArr[0].box_style_formula;
formula = formula.replace(/length/gi, values.length)
formula = formula.replace(/width/gi, values.width)
formula = formula.replace(/height/gi, values.height)
formula = formula.replace(/x1/gi, values.x1)
formula = formula.replace(/x2/gi, values.x2)
formula = formula.replace(/x3/gi, values.x3)
formula = formula.replace(/x4/gi, values.x4)
formula = formula.replace(/x5/gi, values.x5)
formula = formula.replace(/x6/gi, values.x6)
formula = formula.replace(/x7/gi, values.x7)
formula = formula.replace(/x8/gi, values.x8)
formula = formula.replace(/x9/gi, values.x9)
formula = formula.replace(/x10/gi, values.x10)
// disabling the "eval may be harmful" error READ TO UNDERSTAND WHY: https://eslint.org/docs/rules/no-eval
// eslint-disable-next-line
const decimal = eval(formula);
document.getElementById('sqft').value = `${decimal.toFixed(4)} sq. ft`
console.log(document.getElementById('sqft').value)
}
if(boxStyles) {
return (
<>
<Form className="boxcalc-wrapper">
<label>Box Style:<br/>
{touched.style && errors.style && <p>{errors.style}</p>}
<select type="number"
name="style"
multiple={false}
id="style"
className="boxcalc-field"
>
{boxStyles.map((opt) => {
return (<option key={opt.id}>{opt.box_style_name}</option>)
})}
</select>
</label>
<label>Length:<br/>
{touched.length && errors.length && <p>{errors.length}</p>}
<Field type="number"
name="length"
className="boxcalc-field"
/>
</label>
<label>Width:<br/>
{touched.width && errors.width && <p>{errors.width}</p>}
<Field type="number"
name="width"
className="boxcalc-field"
/>
</label>
<label>Height:<br/>
{touched.height && errors.height && <p>{errors.height}</p>}
<Field type="number"
name="height"
className="boxcalc-field"
/>
</label>
<label>X1:<br/>
{touched.x1 && errors.x1 && <p>{errors.x1}</p>}
<Field type="number"
name="x1"
className="boxcalc-field"
/>
</label>
<label>X2:<br/>
{/* {touched.x2 && errors.x2 && <p>{errors.x2}</p>} */}
<Field type="number"
name="x2"
className="boxcalc-field"
/>
</label>
<label>X3:<br/>
<Field type="number"
name="x3"
className="boxcalc-field"
/>
</label>
<label>X4:<br/>
<Field type="number"
name="x4"
className="boxcalc-field"
/>
</label>
<label>X5:<br/>
<Field type="number"
name="x5"
className="boxcalc-field"
/>
</label>
<label>X6:<br/>
<Field type="number"
name="x6"
className="boxcalc-field"
/>
</label>
<label>X7:<br/>
<Field type="number"
name="x7"
className="boxcalc-field"
/>
</label>
<label>X8:<br/>
<Field type="number"
name="x8"
className="boxcalc-field"
/>
</label>
<label>X9:<br/>
<Field type="number"
name="x9"
className="boxcalc-field"
/>
</label>
<label>X10:<br/>
<Field type="number"
name="x10"
className="boxcalc-field"
/>
</label> */}
<label>Name Box:<br/>
<Field type="number"
name="name"
className="boxcalc-field"
/>
</label>
<button className="calculate-box" onClick={calculateFootage}>Calculate</button>
<label>Square Footage:<br/>
<Field
type="text"
name="footage"
className="boxcalc-field"
id="sqft"
readOnly={true}
/>
</label>
<p className="save-question">Need to save this box?</p>
<div className="save-btn-wrapper">
<p className="no-thanks">No thanks</p>
<button className="save-btn">Save</button>
</div>
</Form>
</>
);
} else {
return <p></p>
}
}
const FormikBoxCalculator = withFormik({
mapPropsToValues({ style, length, width, height, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, name, sqft, boxStyles }) {
return {
style: style || '',
length: length || '',
width: width || '',
height: height || '',
x1: x1 || '',
x2: x2 || '',
x3: x3 || '',
x4: x4 || '',
x5: x5 || '',
x6: x6 || '',
x7: x7 || '',
x8: x8 || '',
x9: x9 || '',
x10: x10 || '',
name: name || '',
sqft: sqft || '',
boxStyles: boxStyles || ''
}
},
============= YUP VALIDATION SCHEMA ===============
validationSchema: function createSchema() {
return yup.object().shape({
style: yup.string().required("Style is required"),
length: yup.number().required("Length is required"),
width: yup.number().required("Width is required"),
height: yup.number().required("Height is required"),
})},
============== END SCHEMA ==============
})(BoxCalculator);
export default FormikBoxCalculator;
import React,{useState,useffect}来自“React”;
//为http请求导入axios
从“axios”导入axios;
//Formik/yup(表单验证库)导入
从'formik'导入{withFormik,Form,Field}
从“是”以是的形式导入*;
//样式导入
导入“/BoxCalculator.scss”;
const-BoxCalculator=({值,触摸,错误})=>{
//使用state钩子来存储我们在标记中动态呈现的选项
const[boxStyles,setBoxStyles]=useState();
//从页面呈现时的API中提取可能的框公式列表,并将其保存到数组中
useffect(()=>{
axios.get()http://localhost:5000/api/box-样式')
。然后(res=>{
setBoxStyles(res.data.data);
console.log(boxStyles);
})
.catch(错误=>{
控制台日志(err);
});
//下一行通过使用空的依赖项数组消除了linter错误导致的错误
//eslint禁用下一行react HOOK/deps
}, [])
常量calculateFootage=()=>{
//选择用户选择的长方体样式
const style=document.getElementById('style').value;
//过滤数组以根据
让styleFormulaArr=boxStyles.filter(box=>box.box\u style\u name===style)
让公式=styleFormulaArr[0]。长方体\u样式\u公式;
公式=公式.replace(/length/gi,values.length)
公式=公式.replace(/width/gi,values.width)
公式=公式.replace(/height/gi,values.height)
公式=公式.replace(/x1/gi,values.x1)
公式=公式.replace(/x2/gi,values.x2)
公式=公式.replace(/x3/gi,values.x3)
公式=公式.replace(/x4/gi,values.x4)
公式=公式.replace(/x5/gi,values.x5)
公式=公式.replace(/x6/gi,values.x6)
公式=公式.replace(/x7/gi,values.x7)
公式=公式.replace(/x8/gi,values.x8)
公式=公式.replace(/x9/gi,values.x9)
公式=公式.replace(/x10/gi,values.x10)
//禁用“eval可能有害”错误读取以了解原因:https://eslint.org/docs/rules/no-eval
//eslint禁用下一行
常量十进制=评估(公式);
document.getElementById('sqft')。value=`${decimal.toFixed(4)}sq.ft`
console.log(document.getElementById('sqft').value)
}
if(boxStyles){
报税表(
方框样式:
{toucted.style&&errors.style&{errors.style}}
{boxStyles.map((opt)=>{
返回({opt.box\u style\u name})
})}
长度:
{toucted.length&&errors.length&{errors.length}}
宽度:
{toucted.width&&errors.width&&{errors.width}}
高度:
{toucted.height&&errors.height&{errors.height}}
X1:
{toucted.x1&&errors.x1&{errors.x1}}
X2:
{/*{toucted.x2&&errors.x2&{errors.x2}}*/}
X3:
X4:
X5:
X6:
X7:
X8:
X9:
X10:
*/}
名称框:
算计
平方英尺:
需要保存此框吗
不用谢
拯救
);
}否则{
返回
}
}
常量FormikBoxCalculator=带formik({
mapPropsToValues({style,length,width,height,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,name,sqft,boxStyles}){
返回{
风格:风格| |“,
长度:长度| |“”,
宽度:宽度| |“”,
高度:高度| |“”,
x1:x1 | |“”,
x2:x2 | |“”,
x3:x3 | |“,
x4:x4 | |“,
x5:x5 | |“,
x6:x6 | |“,
x7:x7 | |“,
x8:x8 | |“,
x9:x9 | |“,
const attrs = ['length', 'width', 'height', 'x1', 'x2', 'x3', 'x4', .... etc]
for (i in attrs) {
const attr = attrs[i];
if (attr in formula) {
formula = formula.replace(attr, values[attr])
}
}