I am using react.
When I pass props.children to the Header component, I get the following error.
I think the type is correct because I am passing React.
I don't know why the error occurs.
error
react-dom.development.js?61bb:13231 Uncaught Error: Objects are not valid as a React child (found: object with keys {children}). If you meant to render a collection of children, use an array instead.
import React from 'react';
import styled from 'styled-components';
export const Header: React.FC = (children) => {
return <Head>{children}</Head>;
};
const Head = styled.div`
background: #8b8b8b;
`;
const Home = () => {
return (
<div>
<Header>
<span>home</span>
</Header>
<div>
);
};
export default Home;
You just named your props as children, try:
export const Header: React.FC = ({children}) => {
return <Head>{children}</Head>;
};
Let's just take a step back from destructuring for a second because it confuses a lot of JS beginners.
By default, your component receives an argument which is a bunch of properties, so we usually call it props. We can get particular properties from this props object like so:
export const Header = (props) => {
console.log(props)
return <Head>{props.children}</Head>;
};
Then once you get your head around destructuring, you'll notice we can do this in a faster, cleaner manner to get properties from our props object.
export const Header = ({ children }) => {
console.log(children)
return <Head>{children}</Head>;
};
The trade-off is we can't do props.something now, we'll need to add something to the restructure... but our code looks cleaner.
Related
I want to make a ref context, using that context's refs in my sections and then consuming the context in my navbar to use intersectionObserver.
Trying to achieve this at first i created a context with every ref and then using the context in my about component.
The context looks like this:
import React, { createContext, useRef } from "react";
export const RefsContext = createContext();
export const RefsProvider = (props) => {
const aboutRef = useRef();
const shopRef = useRef();
const customersRef = useRef();
return (
<RefsContext.Provider
value={{
aboutRef,
shopRef,
customersRef,
}}
>
{props.children}
</RefsContext.Provider>
);
};
export default RefsProvider;
And this is how i consume that context in my about.js:
First i import the context: import { RefsContext } from "../../../context/refsContext"; then i use it: const { aboutRef } = useContext(RefsContext); and here i use that ref to referenciate a section: <section className="about" id="about" ref={aboutRef}>
I get this error message Uncaught TypeError: Cannot destructure property 'aboutRef' of '(0 , react__WEBPACK_IMPORTED_MODULE_0__.useContext)(...)' as it is undefined. in about.js:10, this line: const { aboutRef } = useContext(RefsContext);
Looks like you forgot to wrap whatever component is using this in RefsProvider. Does that fix this problem?
EDIT: To provide further context, if you use useContext inside a component that is not wrapped in the Provider for the context you are accessing, the value will be undefined. I suspect that is what is happening here.
In order to fix this, you need to wrap the component in RefsProvider
For example:
<RefsProvider>
<YourComponentThatUsesRefsContext />
</RefsProvider>
I have defined a context using createContext that wraps some of my components like
import MyContext from './mycontext.js'
import A from 'a.js';
import B from b.js';
<MyContext>
<A/>
<B/>
</MyContext>
where A is defined something like
import C from './c.js'
const A = () => {
return (<C/>);
}
And C is define something like
import MyContext from 'mycontext.js';
const C = () => {
const { value, setValue } = useContext(MyContext);
return (<div>`This is the value - ${!!value ? value : 'UNK'}`</div>)
}
Finally the context is created like
const MyContext = createContext({value: '', setValue: () => {}});
The problem is that I get a runtime error
TypeError: Object is not iterable (cannot read property Symbol(Symbol.iterator))
From the component C.
I want to make provision for calling C outside of the provider. Not as a wrapped child of the provider. Where does this error come from and how do I work around it?
From only what I can tell from the code snippets it appears you're not rendering any context provider and not providing a context value.
Instead of trying to use the MyContext context as a React component, render the Provider component.
<MyContext.Provider value={{ value: 42, setValue: console.log }}>
<A />
<B />
</MyContext.Provider>
I am trying to do:
Change child state as in this tutorial: Change child state from parent
Tutorial uses class component, I've tried to use function components.It gives an error like "Function components don't have instances so they can't have refs"
So I used forwardRef (for the first time) according to a stackoverflow answer here
Code:
import React,{useRef,forwardRef, useEffect} from "react";
const Component = (props) => {
function sayHello(){
console.log("hello")
}
return <h1>{props.children}</h1>
}
const ForwardComponent = forwardRef((props,ref)=> (<Component ref={ref}> {props.children} </Component>))
export default function App() {
const hello = useRef()
useEffect(()=>{
hello.current.sayHello()
})
return (
<div>
<ForwardComponent ref={hello}>Hello</ForwardComponent>
</div>
);
}
note: I could use context api or redux here, but I believe it should be simpler in my use case. Also I get to learn something new
I have a recompose filter that needs to render two components and pass props from a redux connect to the second component
However the code below never renders the second renderComponent - which is a real shame. Is there a way to get the below working, or should I opt for a regular React component?
import { compose, renderComponent } from "recompose"
import { connect } from "react-redux"
import Filters from "./filter/filter"
import Wrestlers from "./container"
const defaultState = state => ({
collection: state.roster,
})
export default compose(
renderComponent(Filters),
connect(defaultState),
renderComponent(Wrestlers),
)(Wrestlers)
renderComponent always discards the second argument (the base component) and renders the first argument. If you want to render then both, just create a new component and render them. Probably something like:
const Parent = ({ collection }) => (
// You can return an array here if you are using React 16
<div>
<Filters />
<Wrestlers collection={collection} />
<div>
)
export default connect(defaultState)(Parent)
I am creating a bit of a playground to learn react and I've hit a road block with passing props between components. I essentially have two components, 1 that is the base component and then another that renders it out on the page with some extras (which i've removed for simplicity sake). I essentially want to be able to reuse the items in other places.
I'd like to be able to, when rendering the component in the example specify if it is type=submit if nothing specified default to type=button.
I'm clearly missing the point here because I get the error Cannot read property 'props' of undefined with the below code. Any help would be appreciated
Button Component
import React, {PropTypes} from 'react';
import './button_component.scss';
const propTypes = {
type: PropTypes.string
}
const ButtonComponent = () => {
return <button type={this.props.type}>button</button>
}
ButtonComponent.propTypes = propTypes;
export default ButtonComponent;
Then I have a component that outputs my item
import React from 'react';
import ButtonComponent from './button_component';
import Example from './example'
export default () =>
<Example>
<ButtonComponent type='button' />
</Example>;
ButtonComponent is a functional component. Hence, you can not use this.props in its code.
You should introduce props argument
const ButtonComponent = (props) => {
return <button type={props.type}>button</button>
}
Object destructuring and defaultProps can help you make your code simpler
const ButtonComponent = ({ type }) => {
return <button type={type}>button</button>
}
ButtonComponent.defaultProps = {
type: 'button'
}
then you can simply put <ButtonComponent /> to render a button.