使用 React 和重组创建 HoC 时出错
Error creating HoC with React and recompose
使用重组创建 HoC 时出错 withState
和 lifecycle
:
warning.js?8a56:36 Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components). Check the render method of `AppContainer`.
我的组件树是这样的:
export function SimpleImage(props) {
const {
src,
width = 200,
height = 200,
rounded,
circle,
status,
onLoad,
onFail,
} = props;
const mainWrapperStyle = style({
backgroundColor: 'white',
backgroundSize: 'contain',
backgroundRepeat: 'none',
boxSizing: 'border-box',
position: 'relative',
width,
height,
});
const roundedStyle = style({
borderRadius: '10%',
overflow: 'hidden',
});
const circularStyle = style({
borderRadius: '50%',
overflow: 'hidden',
});
const defaultImageStyle = style({
opacity: 0,
transisition: 'opacity 150ms ease',
});
const loadedImageStyle = style({
opacity: 1,
});
let imageStyle = defaultImageStyle;
let wrapperStyle = mainWrapperStyle;
if (rounded) {
wrapperStyle = merge(mainWrapperStyle, roundedStyle);
} else if (circle) {
wrapperStyle = merge(mainWrapperStyle, circularStyle);
}
if (status === LOADED) {
imageStyle = merge(defaultImageStyle, loadedImageStyle);
}
const image = (<img
{...imageStyle}
src={src}
width={width}
height={height}
role="presentation"
onLoad={this.onLoad}
onError={this.onFail}
/>);
let statusIndicator = null;
if (this.state.status === LOADING) {
statusIndicator = (<LoadingIndicator />);
} else if (this.state.status === FAILED) {
statusIndicator = (<ErrorIndicator />);
}
return (<div {...wrapperStyle}>
{statusIndicator}
{image}
</div>);
}
const Image = compose(
withState(
'status',
'setStatus',
({ src })=> src? LOADING: PENDING
),
withProps(
({ setStatus }) => ({
onLoad() {
setStatus(LOADED);
},
onFail() {
setStatus(FAILED);
},
reset() {
setStatus(PENDING)
},
resetToLoading() {
setStatus(LOADING)
},
})),
lifecycle({
componentWillReceiveProps(nextProps) {
if(nextProps.src == null){
this.props.reset();
} else if(nextProps.src !== this.props.src) {
this.props.resetToLoading();
}
}
})
)(SimpleImage);
SimpleImage
组件仍然引用 this
和 state
,尽管它是无状态功能组件。删除这些引用并将 this.onLoad
替换为 onLoad
、将 this.onFail
替换为 onFail
并将 this.state.status
替换为 status
可以正常工作。
更新后的 SimpleImage
组件如下所示:
export function SimpleImage(props) {
const {
src,
width = 200,
height = 200,
rounded,
circle,
status,
onLoad,
onFail,
} = props;
const mainWrapperStyle = style({
backgroundColor: 'white',
backgroundSize: 'contain',
backgroundRepeat: 'none',
boxSizing: 'border-box',
position: 'relative',
width,
height,
});
const roundedStyle = style({
borderRadius: '10%',
overflow: 'hidden',
});
const circularStyle = style({
borderRadius: '50%',
overflow: 'hidden',
});
const defaultImageStyle = style({
opacity: 0,
transisition: 'opacity 150ms ease',
});
const loadedImageStyle = style({
opacity: 1,
});
let imageStyle = defaultImageStyle;
let wrapperStyle = mainWrapperStyle;
if (rounded) {
wrapperStyle = merge(mainWrapperStyle, roundedStyle);
} else if (circle) {
wrapperStyle = merge(mainWrapperStyle, circularStyle);
}
if (status === LOADED) {
imageStyle = merge(defaultImageStyle, loadedImageStyle);
}
debugger
const image = (<img
{...imageStyle}
src={src}
width={width}
height={height}
role="presentation"
onLoad={onLoad}
onError={onFail}
/>);
let statusIndicator = null;
if (status === LOADING) {
statusIndicator = (<LoadingIndicator />);
} else if (status === FAILED) {
statusIndicator = (<ErrorIndicator />);
}
return (<div {...wrapperStyle}>
{statusIndicator}
{image}
</div>);
}
使用重组创建 HoC 时出错 withState
和 lifecycle
:
warning.js?8a56:36 Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components). Check the render method of `AppContainer`.
我的组件树是这样的:
export function SimpleImage(props) {
const {
src,
width = 200,
height = 200,
rounded,
circle,
status,
onLoad,
onFail,
} = props;
const mainWrapperStyle = style({
backgroundColor: 'white',
backgroundSize: 'contain',
backgroundRepeat: 'none',
boxSizing: 'border-box',
position: 'relative',
width,
height,
});
const roundedStyle = style({
borderRadius: '10%',
overflow: 'hidden',
});
const circularStyle = style({
borderRadius: '50%',
overflow: 'hidden',
});
const defaultImageStyle = style({
opacity: 0,
transisition: 'opacity 150ms ease',
});
const loadedImageStyle = style({
opacity: 1,
});
let imageStyle = defaultImageStyle;
let wrapperStyle = mainWrapperStyle;
if (rounded) {
wrapperStyle = merge(mainWrapperStyle, roundedStyle);
} else if (circle) {
wrapperStyle = merge(mainWrapperStyle, circularStyle);
}
if (status === LOADED) {
imageStyle = merge(defaultImageStyle, loadedImageStyle);
}
const image = (<img
{...imageStyle}
src={src}
width={width}
height={height}
role="presentation"
onLoad={this.onLoad}
onError={this.onFail}
/>);
let statusIndicator = null;
if (this.state.status === LOADING) {
statusIndicator = (<LoadingIndicator />);
} else if (this.state.status === FAILED) {
statusIndicator = (<ErrorIndicator />);
}
return (<div {...wrapperStyle}>
{statusIndicator}
{image}
</div>);
}
const Image = compose(
withState(
'status',
'setStatus',
({ src })=> src? LOADING: PENDING
),
withProps(
({ setStatus }) => ({
onLoad() {
setStatus(LOADED);
},
onFail() {
setStatus(FAILED);
},
reset() {
setStatus(PENDING)
},
resetToLoading() {
setStatus(LOADING)
},
})),
lifecycle({
componentWillReceiveProps(nextProps) {
if(nextProps.src == null){
this.props.reset();
} else if(nextProps.src !== this.props.src) {
this.props.resetToLoading();
}
}
})
)(SimpleImage);
SimpleImage
组件仍然引用 this
和 state
,尽管它是无状态功能组件。删除这些引用并将 this.onLoad
替换为 onLoad
、将 this.onFail
替换为 onFail
并将 this.state.status
替换为 status
可以正常工作。
更新后的 SimpleImage
组件如下所示:
export function SimpleImage(props) {
const {
src,
width = 200,
height = 200,
rounded,
circle,
status,
onLoad,
onFail,
} = props;
const mainWrapperStyle = style({
backgroundColor: 'white',
backgroundSize: 'contain',
backgroundRepeat: 'none',
boxSizing: 'border-box',
position: 'relative',
width,
height,
});
const roundedStyle = style({
borderRadius: '10%',
overflow: 'hidden',
});
const circularStyle = style({
borderRadius: '50%',
overflow: 'hidden',
});
const defaultImageStyle = style({
opacity: 0,
transisition: 'opacity 150ms ease',
});
const loadedImageStyle = style({
opacity: 1,
});
let imageStyle = defaultImageStyle;
let wrapperStyle = mainWrapperStyle;
if (rounded) {
wrapperStyle = merge(mainWrapperStyle, roundedStyle);
} else if (circle) {
wrapperStyle = merge(mainWrapperStyle, circularStyle);
}
if (status === LOADED) {
imageStyle = merge(defaultImageStyle, loadedImageStyle);
}
debugger
const image = (<img
{...imageStyle}
src={src}
width={width}
height={height}
role="presentation"
onLoad={onLoad}
onError={onFail}
/>);
let statusIndicator = null;
if (status === LOADING) {
statusIndicator = (<LoadingIndicator />);
} else if (status === FAILED) {
statusIndicator = (<ErrorIndicator />);
}
return (<div {...wrapperStyle}>
{statusIndicator}
{image}
</div>);
}