Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Look at impact of removing deprecated lifecycles #4656

Merged
merged 1 commit into from
Feb 13, 2025
Merged
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
27 changes: 0 additions & 27 deletions compat/src/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,33 +40,6 @@ const onChangeInputType = type => /fil|che|rad/.test(type);
// Some libraries like `react-virtualized` explicitly check for this.
Component.prototype.isReactComponent = {};

// `UNSAFE_*` lifecycle hooks
// Preact only ever invokes the unprefixed methods.
// Here we provide a base "fallback" implementation that calls any defined UNSAFE_ prefixed method.
// - If a component defines its own `componentDidMount()` (including via defineProperty), use that.
// - If a component defines `UNSAFE_componentDidMount()`, `componentDidMount` is the alias getter/setter.
// - If anything assigns to an `UNSAFE_*` property, the assignment is forwarded to the unprefixed property.
// See https://github.com/preactjs/preact/issues/1941
[
'componentWillMount',
'componentWillReceiveProps',
'componentWillUpdate'
].forEach(key => {
Object.defineProperty(Component.prototype, key, {
configurable: true,
get() {
return this['UNSAFE_' + key];
},
set(v) {
Object.defineProperty(this, key, {
configurable: true,
writable: true,
value: v
});
}
});
});

/**
* Proxy render() since React returns a Component reference.
* @param {import('./internal').VNode} vnode VNode tree to render
Expand Down
250 changes: 0 additions & 250 deletions compat/test/browser/component.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,254 +75,4 @@ describe('components', () => {
children: 'second'
});
});

describe('UNSAFE_* lifecycle methods', () => {
it('should support UNSAFE_componentWillMount', () => {
let spy = sinon.spy();

class Foo extends React.Component {
// eslint-disable-next-line camelcase
UNSAFE_componentWillMount() {
spy();
}

render() {
return <h1>foo</h1>;
}
}

React.render(<Foo />, scratch);

expect(spy).to.be.calledOnce;
});

it('should support UNSAFE_componentWillMount #2', () => {
let spy = sinon.spy();

class Foo extends React.Component {
render() {
return <h1>foo</h1>;
}
}

Object.defineProperty(Foo.prototype, 'UNSAFE_componentWillMount', {
value: spy
});

React.render(<Foo />, scratch);
expect(spy).to.be.calledOnce;
});

it('should support UNSAFE_componentWillReceiveProps', () => {
let spy = sinon.spy();

class Foo extends React.Component {
// eslint-disable-next-line camelcase
UNSAFE_componentWillReceiveProps() {
spy();
}

render() {
return <h1>foo</h1>;
}
}

React.render(<Foo />, scratch);
// Trigger an update
React.render(<Foo />, scratch);
expect(spy).to.be.calledOnce;
});

it('should support UNSAFE_componentWillReceiveProps #2', () => {
let spy = sinon.spy();

class Foo extends React.Component {
render() {
return <h1>foo</h1>;
}
}

Object.defineProperty(Foo.prototype, 'UNSAFE_componentWillReceiveProps', {
value: spy
});

React.render(<Foo />, scratch);
// Trigger an update
React.render(<Foo />, scratch);
expect(spy).to.be.calledOnce;
});

it('should support UNSAFE_componentWillUpdate', () => {
let spy = sinon.spy();

class Foo extends React.Component {
// eslint-disable-next-line camelcase
UNSAFE_componentWillUpdate() {
spy();
}

render() {
return <h1>foo</h1>;
}
}

React.render(<Foo />, scratch);
// Trigger an update
React.render(<Foo />, scratch);
expect(spy).to.be.calledOnce;
});

it('should support UNSAFE_componentWillUpdate #2', () => {
let spy = sinon.spy();

class Foo extends React.Component {
render() {
return <h1>foo</h1>;
}
}

Object.defineProperty(Foo.prototype, 'UNSAFE_componentWillUpdate', {
value: spy
});

React.render(<Foo />, scratch);
// Trigger an update
React.render(<Foo />, scratch);
expect(spy).to.be.calledOnce;
});

it('should alias UNSAFE_* method to non-prefixed variant', () => {
let inst;
class Foo extends React.Component {
// eslint-disable-next-line camelcase
UNSAFE_componentWillMount() {}
// eslint-disable-next-line camelcase
UNSAFE_componentWillReceiveProps() {}
// eslint-disable-next-line camelcase
UNSAFE_componentWillUpdate() {}
render() {
inst = this;
return <div>foo</div>;
}
}

React.render(<Foo />, scratch);

expect(inst.UNSAFE_componentWillMount).to.equal(inst.componentWillMount);
expect(inst.UNSAFE_componentWillReceiveProps).to.equal(
inst.UNSAFE_componentWillReceiveProps
);
expect(inst.UNSAFE_componentWillUpdate).to.equal(
inst.UNSAFE_componentWillUpdate
);
});

it('should call UNSAFE_* methods through Suspense with wrapper component #2525', () => {
class Page extends React.Component {
UNSAFE_componentWillMount() {}
render() {
return <h1>Example</h1>;
}
}

const Wrapper = () => <Page />;

sinon.spy(Page.prototype, 'UNSAFE_componentWillMount');

React.render(
<React.Suspense fallback={<div>fallback</div>}>
<Wrapper />
</React.Suspense>,
scratch
);

expect(scratch.innerHTML).to.equal('<h1>Example</h1>');
expect(Page.prototype.UNSAFE_componentWillMount).to.have.been.called;
});
});

describe('defaultProps', () => {
it('should apply default props on initial render', () => {
class WithDefaultProps extends Component {
constructor(props, context) {
super(props, context);
expect(props).to.be.deep.equal({
fieldA: 1,
fieldB: 2,
fieldC: 1,
fieldD: 2
});
}
render() {
return <div />;
}
}
WithDefaultProps.defaultProps = { fieldC: 1, fieldD: 1 };
React.render(
<WithDefaultProps fieldA={1} fieldB={2} fieldD={2} />,
scratch
);
});

it('should apply default props on rerender', () => {
let doRender;
class Outer extends Component {
constructor() {
super();
this.state = { i: 1 };
}
componentDidMount() {
doRender = () => this.setState({ i: 2 });
}
render(props, { i }) {
return <WithDefaultProps fieldA={1} fieldB={i} fieldD={i} />;
}
}
class WithDefaultProps extends Component {
constructor(props, context) {
super(props, context);
this.ctor(props, context);
}
ctor() {}
componentWillReceiveProps() {}
render() {
return <div />;
}
}
WithDefaultProps.defaultProps = { fieldC: 1, fieldD: 1 };

let proto = WithDefaultProps.prototype;
sinon.spy(proto, 'ctor');
sinon.spy(proto, 'componentWillReceiveProps');
sinon.spy(proto, 'render');

React.render(<Outer />, scratch);
doRender();

const PROPS1 = {
fieldA: 1,
fieldB: 1,
fieldC: 1,
fieldD: 1
};

const PROPS2 = {
fieldA: 1,
fieldB: 2,
fieldC: 1,
fieldD: 2
};

expect(proto.ctor).to.have.been.calledWithMatch(PROPS1);
expect(proto.render).to.have.been.calledWithMatch(PROPS1);

rerender();

// expect(proto.ctor).to.have.been.calledWith(PROPS2);
expect(proto.componentWillReceiveProps).to.have.been.calledWithMatch(
PROPS2
);
expect(proto.render).to.have.been.calledWithMatch(PROPS2);
});
});
});
Loading