- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我被这个问题困住了,我正在使用 redux 来解决这个问题,并将问题分为 4 个部分。我想要实现的是将组件 Prop 与另一个组件(也称为 PropEditor 表单)内的 UI 动态映射。我在说什么,首先看到它尚未实现,但它只是我想要实现的原型(prototype)。
如果您为我提供更好的解决方案来解决这个问题,我也将不胜感激。
我的方法:
我有一个名为 Heading.js
的组件其中包含 2 个 Prop hasFruit
一个 bool 类型和一个 fruitName
字符串类型。它可以是任何库中的组件,但让我们从简单开始。
src/components/Heading.js
import React from 'react';
export const Heading = (props) => {
const { hasFruit, fruitName } = props;
return <h1>Fruit name will show { hasFruit ? fruitName : 'Oh no!'}</h1>
};
PropEditor
上将此组件 Prop 显示为 UI成分。所以,我必须为 Prop 定义不同的 UI 组件。因此,我创建了 2 个输入类型组件。
import React from 'react';
import PropTypes from 'prop-types';
const propTypes = {
/** object for the boolean input type. */
prop: PropTypes.shape({
/** It will be the name of the prop. */
name: PropTypes.string,
/** It will be the value of the prop. */
value: PropTypes.bool,
}),
/** onChange handler for the input */
onChange: PropTypes.func
};
const defaultProps = {
prop: {},
onChange: (value) => value,
};
const Boolean = (props) => {
const { prop, onChange } = props;
return (
<input
id={prop.name}
name={prop.name}
type="checkbox"
onChange={(event) => onChange(event.target.checked)}
checked={prop.value}
/>
);
};
Boolean.propTypes = propTypes;
Boolean.defaultProps = defaultProps;
export default Boolean;
import React from 'react';
import PropTypes from 'prop-types';
const propTypes = {
/** object for the text input type. */
prop: PropTypes.shape({
/** It will be the name of the prop. */
name: PropTypes.string,
/** It will be the value of the prop. */
value: PropTypes.string
}),
/** onChange handler for the input */
onChange: PropTypes.func
};
const defaultProps = {
prop: {},
onChange: (value) => value,
};
const Text = (props) => {
const { prop, onChange } = props;
const handleChange = (event) => {
const { value } = event.target;
onChange(value);
};
return (
<input
id={prop.name}
type="text"
onChange={handleChange}
value={prop.value}
/>
);
};
Text.propTypes = propTypes;
Text.defaultProps = defaultProps;
export default Text;
PropForm
中导入这些组件组件是
PropEditor
的子组件成分。所以我们可以映射这些类型。
import BooleanType from './Boolean';
import TextType from './Text';
export default {
boolean: BooleanType,
text: TextType,
};
SET_PROP
在商店和
SET_PROP_VALUE
上设置 Prop 数据即通过
PropEditor
调度组件在输入更改时更新输入的值。
// PropEditor Actions
// One single prop
export const SET_PROP = 'SET_PROP';
// One single prop value
export const SET_PROP_VALUE = 'SET_PROP_VALUE';
import * as actionTypes from './actionTypes';
// Prop related action creators
/**
* @param prop {Object} - The prop object
* @return {{type: {string}, data: {Object}}}
*/
export const setProp = (prop) => {
return {
type: actionTypes.SET_PROP,
data: prop
};
};
// Prop value related actions
/**
* @param prop {Object} - The prop object
* @return {{type: {string}, data: {Object}}}
*/
export const setPropValue = (prop) => {
return {
type: actionTypes.SET_PROP_VALUE,
data: prop
};
};
import * as actionTypes from './actionTypes';
const INITIAL_STATE = {};
export const propReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
// Prop Actions
case (actionTypes.SET_PROP):
const { data } = action;
return { ...state, [data.name]: {...data} };
// Prop Value Actions
case (actionTypes.SET_PROP_VALUE):
return { ...state, [action.data.name]: { ...state[action.data.name], value: action.data.value } };
default:
return state;
}
};
import { createStore } from 'redux';
import { propReducer } from './PropReducer';
const REDUX_DEV_TOOL = window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__();
export const store = createStore(propReducer, REDUX_DEV_TOOL);
App
与
react-redux
DOM 上的提供程序。
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { store } from './editor/PropStore';
import App from './App';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
Heading.js
带有 UI 的 Prop
PropEditor
成分?
HOC
用户必须调用一些在幕后帮助我们动态填充商店的函数。我创建了一些函数,如
boolean
和
text
这将调度一个名为
SET_PROP
的 Action 填充商店状态。
import { store } from './PropStore';
import { setProp } from './PropActions';
/**
* @param name {string} - The name of the prop
* @param options {Object} - The prop with some additional properties
* @return {*} - Returns the associated value of the prop
*/
const prop = (name, options) => {
const defaultValue = options.value;
// Create an object and merge with additional properties like `defaultValue`
const prop = {
...options,
name,
defaultValue,
};
store.dispatch(setProp(prop));
return defaultValue;
};
/**
* @param name {string} - The name of the prop
* @param value {boolean} - The value of the prop
* @return {boolean} - Returns the value of the prop
*/
export const boolean = (name, value) => {
// Returns the value of the prop
return prop(name, { type: 'boolean', value });
};
/**
* @param name {string} - The name of the prop
* @param value {string} - The value of the prop
* @return {text} - Returns the value of the prop
*/
export const text = (name, value) => {
// Returns the value of the prop
return prop(name, { type: 'text', value });
};
HOC
组件和 PropEditor
在 DOM 上:
import React from 'react';
import { boolean, text } from './editor';
import { Heading } from './components/Heading';
// WithHeading Block
export const WithHeading = () => {
const boolVal = boolean('hasFruit', true);
const textVal = text('fruitName', 'Apple');
return (<Heading hasFruit={boolVal} fruitName={textVal}/>);
};
App
成分。
import React from 'react';
import { PropEditor } from './editor/components/PropEditor';
import { WithHeading } from './blocks';
const App = () => {
return (
<div className="App">
{/* PropEditor */}
<PropEditor />
{/* Blocks */}
<WithHeading/>
</div>
);
};
export default App;
PropEditor
组件
PropEditor
将在任何输入更改时调度一个 Action ,但请记住我们所有的
props
被转换为用于渲染 UI 的对象数组,这些对象将在
PropForm
内部传递成分。
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { PropForm } from './PropForm';
import { setPropValue } from '../PropActions';
export const PropEditor = () => {
// Alternative to connect’s mapStateToProps
const props = useSelector(state => {
return state;
});
// Alternative to connect’s mapDispatchToProps
// By default, the return value of `useDispatch` is the standard Dispatch type defined by the
// Redux core types, so no declarations are needed.
const dispatch = useDispatch();
const handleChange = (dataFromChild) => {
dispatch(setPropValue(dataFromChild));
};
// Convert objects into array of objects
const propsArray = Object.keys(props).map(key => {
return props[key];
});
return (
<div>
{/* Editor */}
<div style={styles.editor}>
<div style={styles.container}>
{ propsArray.length === 0
? <h1 style={styles.noProps}>No Props</h1>
: <PropForm props={propsArray} onFieldChange={handleChange} />
}
</div>
</div>
</div>
);
};
import React from 'react';
import PropTypes from 'prop-types';
import TypeMap from './types';
const propTypes = {
props: PropTypes.arrayOf(PropTypes.object).isRequired,
onFieldChange: PropTypes.func.isRequired
};
// InvalidType component
const InvalidType = () => (<span>Invalid Type</span>);
export const PropForm = (properties) => {
/**
* @param name {string} - Name of the prop
* @param type {string} - InputType of the prop
* @return {Function} - Returns a function
*/
const makeChangeHandler = (name, type) => {
const { onFieldChange } = properties;
return (value = '') => {
// `change` will be an object and value will be from the onChange
const change = {name, type, value};
onFieldChange(change);
};
};
// Take props from the component properties
const { props } = properties;
return (
<form>
{
props.map(prop => {
const changeHandler = makeChangeHandler(prop.name, prop.type);
// Returns a component based on the `type`
// if the `type` is boolean then
// return Boolean() component
let InputType = TypeMap[prop.type] || InvalidType;
return (
<div style={{marginBottom: '16px'}} key={prop.name}>
<label htmlFor={prop.name}>{`${prop.name}`}</label>
<InputType prop={prop} onChange={changeHandler}/>
</div>
);
})
}
</form>
);
};
PropForm.propTypes = propTypes;
Heading
SET_PROP_VALUE
时组件未发生操作是在
PropEditor
内的输入更改时分派(dispatch)的成分。
Heading
没有发生。
HOC
text()
和
boolean()
函数没有返回更新的值。
WithHeading
组件与
react-redux
.我知道这一点,但有没有办法像
boolean('hasFruit', true)
这样的功能和
text('fruitName', 'Apple')
更新商店状态时返回最新值?
最佳答案
我在这里创建了 4 个演示,每个演示都是前一个演示的扩展版本:
1) 通过 mapStateToProps 连接痛点和更新组件
2) 通过使用 useSelector
const boolVal = useSelector(state => state.hasFruit ? state.hasFruit.value : false );
const booleanVal = useSelector(state => booleanSelector(state, "hasFruit"));
const booleanVal = useGetValueFromStore("hasFruit");
The problem is re-rendering of the Heading component is not happening
store
上发生了一些变化,您需要拨打
connect
与商店建立联系并了解最新变化。
blocks.js
的更新代码:
// WithHeading Block
const WithHeading = props => {
useEffect(() => {
boolean("hasFruit", true); // <--- Setting initial value
text("fruitName", "Apple"); // <--- Setting initial value
}, []); // <----- get called only on mount
return <Heading hasFruit={props.boolVal} fruitName={props.textVal} />;
};
// to get updated state values inside the component as props
const mapStateToProps = state => {
return {
boolVal: state.hasFruit ? state.hasFruit.value : false,
textVal: state.fruitName ? state.fruitName.value : ""
};
};
// to make connection with store
export default connect(mapStateToProps)(WithHeading);
useSelector
:
// WithHeading Block
const WithHeading = props => {
// console.log(props);
const boolVal = useSelector(state =>
state.hasFruit ? state.hasFruit.value : false
);
const textVal = useSelector(state =>
state.fruitName ? state.fruitName.value : ""
);
useEffect(() => {
boolean("hasFruit", true);
text("fruitName", "Apple");
}, []);
return <Heading hasFruit={boolVal} fruitName={textVal} />;
};
export default WithHeading;
const WithHeading = props => {
// you can pass the input names here, and get value of it
const booleanVal = useSelector(state => booleanSelector(state, "hasFruit"));
const textVal = useSelector(state => textValSelector(state, "fruitName"));
useEffect(() => {
boolean("hasFruit", true);
text("fruitName", "Apple");
}, []);
return <Heading hasFruit={booleanVal} fruitName={textVal} />;
};
useSelector
的自定义 Hook :
// a function that will return updated value of given name
const useGetValueFromStore = name => {
const value = useSelector(state => (state[name] ? state[name].value : ""));
return value;
};
// WithHeading Block
const WithHeading = props => {
//------- all you need is just to pass the name --------
const booleanVal = useGetValueFromStore("hasFruit");
const textVal = useGetValueFromStore("fruitName");
useEffect(() => {
boolean("hasFruit", true);
text("fruitName", "Apple");
}, []);
return <Heading hasFruit={booleanVal} fruitName={textVal} />;
};
export default WithHeading;
关于reactjs - 当 store 状态改变时重新渲染组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62309220/
SQLite、Content provider 和 Shared Preference 之间的所有已知区别。 但我想知道什么时候需要根据情况使用 SQLite 或 Content Provider 或
警告:我正在使用一个我无法完全控制的后端,所以我正在努力解决 Backbone 中的一些注意事项,这些注意事项可能在其他地方更好地解决......不幸的是,我别无选择,只能在这里处理它们! 所以,我的
我一整天都在挣扎。我的预输入搜索表达式与远程 json 数据完美配合。但是当我尝试使用相同的 json 数据作为预取数据时,建议为空。点击第一个标志后,我收到预定义消息“无法找到任何内容...”,结果
我正在制作一个模拟 NHL 选秀彩票的程序,其中屏幕右侧应该有一个 JTextField,并且在左侧绘制弹跳的选秀球。我创建了一个名为 Ball 的类,它实现了 Runnable,并在我的主 Draf
这个问题已经有答案了: How can I calculate a time span in Java and format the output? (18 个回答) 已关闭 9 年前。 这是我的代码
我有一个 ASP.NET Web API 应用程序在我的本地 IIS 实例上运行。 Web 应用程序配置有 CORS。我调用的 Web API 方法类似于: [POST("/API/{foo}/{ba
我将用户输入的时间和日期作为: DatePicker dp = (DatePicker) findViewById(R.id.datePicker); TimePicker tp = (TimePic
放宽“邻居”的标准是否足够,或者是否有其他标准行动可以采取? 最佳答案 如果所有相邻解决方案都是 Tabu,则听起来您的 Tabu 列表的大小太长或您的释放策略太严格。一个好的 Tabu 列表长度是
我正在阅读来自 cppreference 的代码示例: #include #include #include #include template void print_queue(T& q)
我快疯了,我试图理解工具提示的行为,但没有成功。 1. 第一个问题是当我尝试通过插件(按钮 1)在点击事件中使用它时 -> 如果您转到 Fiddle,您会在“内容”内看到该函数' 每次点击都会调用该属
我在功能组件中有以下代码: const [ folder, setFolder ] = useState([]); const folderData = useContext(FolderContex
我在使用预签名网址和 AFNetworking 3.0 从 S3 获取图像时遇到问题。我可以使用 NSMutableURLRequest 和 NSURLSession 获取图像,但是当我使用 AFHT
我正在使用 Oracle ojdbc 12 和 Java 8 处理 Oracle UCP 管理器的问题。当 UCP 池启动失败时,我希望关闭它创建的连接。 当池初始化期间遇到 ORA-02391:超过
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve
引用这个plunker: https://plnkr.co/edit/GWsbdDWVvBYNMqyxzlLY?p=preview 我在 styles.css 文件和 src/app.ts 文件中指定
为什么我的条形这么细?我尝试将宽度设置为 1,它们变得非常厚。我不知道还能尝试什么。默认厚度为 0.8,这是应该的样子吗? import matplotlib.pyplot as plt import
当我编写时,查询按预期执行: SELECT id, day2.count - day1.count AS diff FROM day1 NATURAL JOIN day2; 但我真正想要的是右连接。当
我有以下时间数据: 0 08/01/16 13:07:46,335437 1 18/02/16 08:40:40,565575 2 14/01/16 22:2
一些背景知识 -我的 NodeJS 服务器在端口 3001 上运行,我的 React 应用程序在端口 3000 上运行。我在 React 应用程序 package.json 中设置了一个代理来代理对端
我面临着一个愚蠢的问题。我试图在我的 Angular 应用程序中延迟加载我的图像,我已经尝试过这个2: 但是他们都设置了 src attr 而不是 data-src,我在这里遗漏了什么吗?保留 d
我是一名优秀的程序员,十分优秀!