Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions commonjs/withJob.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ function withJob(config) {

this.setState({
data: result ? result.data : null,
error: null,
error: result ? result.error : null,
completed: result != null
});
}
Expand Down Expand Up @@ -140,7 +140,6 @@ function withJob(config) {
error = _state.error,
completed = _state.completed;


if (error) {
return ErrorComponent ? _react2.default.createElement(ErrorComponent, _extends({}, this.props, { error: error })) : null;
}
Expand Down Expand Up @@ -210,7 +209,17 @@ function withJob(config) {
// eslint-disable-next-line no-console
console.warn('Failed to resolve job');
// eslint-disable-next-line no-console
console.warn(error);
console.warn(error.message);
// eslint-disable-next-line no-console
console.warn(error.stack);
if (_this2.context.jobs) {
_this2.context.jobs.register(id, {
error: {
message: error.message,
stack: error.stack
}
});
}
}
// Ensures asyncBootstrap stops
return false;
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 28 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
{
"name": "react-jobs",
"version": "1.0.0",
"description":
"Attach asynchronous/synchronous \"jobs\" to your components, with SSR support.",
"description": "Attach asynchronous/synchronous \"jobs\" to your components, with SSR support.",
"license": "MIT",
"main": "commonjs/index.js",
"files": ["*.js", "*.md", "umd", "commonjs", "ssr.js"],
"files": [
"*.js",
"*.md",
"umd",
"commonjs",
"ssr.js"
],
"repository": {
"type": "git",
"url": "https://github.com/ctrlplusb/react-jobs.git"
Expand All @@ -24,8 +29,7 @@
],
"scripts": {
"build": "babel-node ./tools/scripts/build.js",
"clean":
"rimraf ./commonjs && rimraf ./umd && rimraf ./coverage && rimraf ./flow-coverage && rimraf ./umd",
"clean": "rimraf ./commonjs && rimraf ./umd && rimraf ./coverage && rimraf ./flow-coverage && rimraf ./umd",
"lint": "eslint src",
"precommit": "lint-staged",
"prepush": "jest",
Expand All @@ -36,7 +40,7 @@
},
"peerDependencies": {
"prop-types": "^15.0.0",
"react": "^14.0.0 || ^15.0.0"
"react": "^14.0.0 || ^15.0.0 || ^16.0.0"
},
"devDependencies": {
"app-root-dir": "1.0.2",
Expand Down Expand Up @@ -83,14 +87,21 @@
"webpack-hot-middleware": "^2.19.1"
},
"jest": {
"collectCoverageFrom": ["src/**/*.{js,jsx}"],
"snapshotSerializers": ["<rootDir>/node_modules/enzyme-to-json/serializer"],
"collectCoverageFrom": [
"src/**/*.{js,jsx}"
],
"snapshotSerializers": [
"<rootDir>/node_modules/enzyme-to-json/serializer"
],
"testPathIgnorePatterns": [
"<rootDir>/(commonjs|coverage|flow-typed|node_modules|tools|umd)/"
]
},
"lint-staged": {
"src/**/*.js": ["prettier --write", "git add"]
"src/**/*.js": [
"prettier --write",
"git add"
]
},
"eslintConfig": {
"root": true,
Expand All @@ -103,7 +114,10 @@
"extends": "airbnb",
"rules": {
"array-callback-return": 0,
"arrow-parens": ["error", "as-needed"],
"arrow-parens": [
"error",
"as-needed"
],
"camelcase": 0,
"import/prefer-default-export": 0,
"import/no-extraneous-dependencies": 0,
Expand All @@ -114,7 +128,10 @@
"no-nested-ternary": 0,
"react/no-array-index-key": 0,
"react/react-in-jsx-scope": 0,
"semi": [2, "never"],
"semi": [
2,
"never"
],
"react/forbid-prop-types": 0,
"react/jsx-filename-extension": 0,
"react/sort-comp": 0
Expand Down
30 changes: 27 additions & 3 deletions src/__tests__/__snapshots__/integration.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`integration tests render server and client 1`] = `"<div><div>Hello<div><div>World</div></div></div><div>Goodbye</div></div>"`;
exports[`integration tests render server and client 1`] = `"<div><div>Hello<div><div>World</div></div></div><div>Goodbye</div><div>Oh noes!</div></div>"`;

exports[`integration tests render server and client 2`] = `
Object {
Expand All @@ -14,6 +14,12 @@ Object {
"3": Object {
"data": "Goodbye",
},
"4": Object {
"error": Object {
"message": "Oh noes!",
"stack": "fake stack",
},
},
},
}
`;
Expand Down Expand Up @@ -57,7 +63,20 @@ exports[`integration tests render server and client 3`] = `
</div>
</ResultRenderer>
</WithJob(ResultRenderer)>
<WithJob(ResultRenderer) />
<WithJob(ResultRenderer)>
<ErrorComponent
error={
Object {
"message": "Oh noes!",
"stack": "fake stack",
}
}
>
<div>
Oh noes!
</div>
</ErrorComponent>
</WithJob(ResultRenderer)>
</div>
</JobProvider>
`;
Expand Down Expand Up @@ -103,7 +122,12 @@ exports[`integration tests render server and client 4`] = `
</WithJob(ResultRenderer)>
<WithJob(ResultRenderer)>
<ErrorComponent
error={[Error: Oh noes!]}
error={
Object {
"message": "Oh noes!",
"stack": "fake stack",
}
}
>
<div>
Oh noes!
Expand Down
4 changes: 3 additions & 1 deletion src/__tests__/integration.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ function ResultRenderer({ jobResult, children }) {
)
}
const ErrorComponent = ({ error }) => <div>{error ? error.message : null}</div>
const error = new Error('Oh noes!')
error.stack = 'fake stack'

const createComponents = () => ({
Hello: withJob({ work: () => resolveAfter(workTime, 'Hello') })(
Expand All @@ -30,7 +32,7 @@ const createComponents = () => ({
ResultRenderer,
),
Fail: withJob({
work: () => rejectAfter(workTime, new Error('Oh noes!')),
work: () => rejectAfter(workTime, error),
ErrorComponent,
})(ResultRenderer),
})
Expand Down
55 changes: 31 additions & 24 deletions src/withJob.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default function withJob(config) {
let id

class ComponentWithJob extends Component {
static displayName = `WithJob(${getDisplayName(WrappedComponent)})`;
static displayName = `WithJob(${getDisplayName(WrappedComponent)})`

static contextTypes = {
jobs: PropTypes.shape({
Expand All @@ -42,7 +42,7 @@ export default function withJob(config) {
getRehydrate: PropTypes.func.isRequired,
removeRehydrate: PropTypes.func.isRequired,
}),
};
}

constructor(props, context) {
super(props, context)
Expand All @@ -69,14 +69,15 @@ export default function withJob(config) {
let result

if (this.context.jobs) {
result = env === 'browser'
? this.context.jobs.getRehydrate(id)
: this.context.jobs.get(id)
result =
env === 'browser'
? this.context.jobs.getRehydrate(id)
: this.context.jobs.get(id)
}

this.setState({
data: result ? result.data : null,
error: null,
error: result ? result.error : null,
completed: result != null,
})
}
Expand Down Expand Up @@ -107,7 +108,7 @@ export default function withJob(config) {
}
}

resolveWork = (props) => {
resolveWork = props => {
let workDefinition

this.setState({ completed: false, data: null, error: null })
Expand All @@ -123,7 +124,7 @@ export default function withJob(config) {
if (isPromise(workDefinition)) {
// Asynchronous result.
return workDefinition
.then((data) => {
.then(data => {
if (this.unmounted) {
return undefined
}
Expand All @@ -134,27 +135,34 @@ export default function withJob(config) {
// Ensures asyncBootstrap continues
return true
})
.catch((error) => {
.catch(error => {
if (this.unmounted) {
return undefined
}
if (env === 'browser') {
setTimeout(
() => {
if (!this.unmounted) {
this.setState({ completed: true, error })
}
},
16,
)
setTimeout(() => {
if (!this.unmounted) {
this.setState({ completed: true, error })
}
}, 16)
} else {
// node
// We will at least log the error so that user isn't completely
// unaware of an error occurring.
// eslint-disable-next-line no-console
console.warn('Failed to resolve job')
// eslint-disable-next-line no-console
console.warn(error)
console.warn(error.message)
// eslint-disable-next-line no-console
console.warn(error.stack)
if (this.context.jobs) {
this.context.jobs.register(id, {
error: {
message: error.message,
stack: error.stack,
},
})
}
}
// Ensures asyncBootstrap stops
return false
Expand All @@ -166,21 +174,20 @@ export default function withJob(config) {

// Ensures asyncBootstrap continues
return true
};
}

getJobState = () => ({
completed: this.state.completed,
error: this.state.error,
data: this.state.data,
});
})

render() {
const { data, error, completed } = this.state

if (error) {
return ErrorComponent
? <ErrorComponent {...this.props} error={error} />
: null
return ErrorComponent ? (
<ErrorComponent {...this.props} error={error} />
) : null
}
if (!completed) {
return LoadingComponent ? <LoadingComponent {...this.props} /> : null
Expand Down
15 changes: 12 additions & 3 deletions umd/react-jobs.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ function withJob(config) {

this.setState({
data: result ? result.data : null,
error: null,
error: result ? result.error : null,
completed: result != null
});
}
Expand Down Expand Up @@ -296,7 +296,6 @@ function withJob(config) {
error = _state.error,
completed = _state.completed;


if (error) {
return ErrorComponent ? _react2.default.createElement(ErrorComponent, _extends({}, this.props, { error: error })) : null;
}
Expand Down Expand Up @@ -366,7 +365,17 @@ function withJob(config) {
// eslint-disable-next-line no-console
console.warn('Failed to resolve job');
// eslint-disable-next-line no-console
console.warn(error);
console.warn(error.message);
// eslint-disable-next-line no-console
console.warn(error.stack);
if (_this2.context.jobs) {
_this2.context.jobs.register(id, {
error: {
message: error.message,
stack: error.stack
}
});
}
}
// Ensures asyncBootstrap stops
return false;
Expand Down
2 changes: 1 addition & 1 deletion umd/react-jobs.min.js

Large diffs are not rendered by default.