![](/img/trans.png)
[英]React Redux updates state, but no re-renders, and props is undefined in render(){}
[英]React redux state is undefined on first render despite of initlizedState
Redux 狀態在第一次渲染中未定義,我在減速器中返回了 initilizedState = {}
store.js
const store = createStore(
rootReducer,
compose(
applyMiddleware(thunk),
window.devToolsExtension ? window.devToolsExtension() : (f) => f
)
)
export default store
rootReducer.js
const rootReducer = combineReducers({
search: searchReducer,
product: productReducer,
})
export default rootReducer
減速器.js
const initialState = {}
const productReducer = (state = initialState, action) => {
const { type, payload } = action
switch (type) {
case PRODUCTS_ALL:
console.log('reducer')
return { ...state, items: payload }
default:
return state
}
}
export default productReducer
動作.js
const products = axios.create({
baseURL: 'http://localhost:8001/api/products',
})
export const allProducts = () => async (dispatch) => {
console.log('fetching')
await products.get('/').then((res) => {
dispatch({
type: PRODUCTS_ALL,
payload: res.data,
})
})
}
雖然我在我的提要容器中使用了 connect()
Feed.js
function Feed({ allProducts, product }) {
const [productItems, setProductItems] = useState()
const [loading, setLoading] = useState(false)
React.useEffect(() => {
allProducts()
console.log(product)
}, [])
return (
<div className='feed__content'>
{loading ? (
<Loader
type='Oval'
color='#212121'
height={100}
width={100}
/>
) : (
<div className='feed__products'>
<div className='feed__productsList'>
{product.map((product) => {
return (
<Product
name={product.name}
image={product.image}
price={product.price}
/>
)
})}
</div>
</div>
)}
</div>
)
}
const mapStateToProps = (state) => ({
product: state.product.items,
})
const mapDispatchToProps = (dispatch) => {
return {
allProducts: () => dispatch(allProducts()),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Feed)
如果您查看控制台上的數據,您將看到 undefined 但如果我添加一個 useEffect 依賴項,它將創建一個循環,其中第一個是未定義的,其余的是我想要的數據。 因為這個問題,當我想用 map 渲染產品時,它會拋出一個錯誤,說 can't map undefiend 。
我怎么解決這個問題
您嘗試在 redux 中執行異步操作的代碼的 A/c。 為此,您應該使用 redux-saga 或 redux-thunk。
但是您可以通過以下方式實現輸出,而無需使用 redux-saga 或 thunk。
通過以下方式修改您的代碼:
Feed.js
function Feed({ allProducts, product }) {
// Set loading to true inititally
const [loading, setLoading] = useState(true);
React.useEffect(() => {
// Make your api call here once its complete and you get a res,
// dispatch the referred action with response as payload.
(async () => {
const products = axios.create({
baseURL: "http://localhost:8001/api/products",
});
const {data} = await products.get("/");
allProducts(data);
})()
// This call is only made when you load it for the first time, if it
// depends
// on something add that dependencies in the dependency array of //
// useEffect.
}, []);
// once store is updated with the passed payload. Set loading to
// false.
React.useEffect(() => {
if(product){
setLoading(false);
}
}, [product])
return (
<div className="feed__content">
{loading ? (
<Loader type="Oval" color="#212121" height={100} width={100} />
) : (
<div className="feed__products">
<div className="feed__productsList">
{product.map((product) => {
return (
<Product
name={product.name}
image={product.image}
price={product.price}
/>
);
})}
</div>
</div>
)}
</div>
);
}
const mapStateToProps = ({product}) => ({
product: product?.items,
});
// here we have a payload to pass
const mapDispatchToProps = (dispatch) => {
return {
allProducts: (payload) => dispatch(allProducts(payload)),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Feed);
行動
export const allProducts = (payload) => ({
type: "PRODUCTS_ALL",
payload,
});
減速器
const productReducer = (state = initialState, action) => {
const { type, payload } = action
switch (type) {
case "PRODUCTS_ALL":
return { ...state, items: payload }
default:
return state
}
}
導出默認 productReducer
在Feed.js
中,您沒有獲得完整的狀態片段。 您正試圖訪問里面的關鍵item
。
const mapStateToProps = (state) => ({
product: state.product.items,
})
更改您的initialState
以包含該鍵,您的代碼應該沒問題
const initialState = {
items: []
}
Joel Jaimon代碼運行良好。
在我的代碼中我添加了
const initialState = {
items: []
}
根據@Andrew和 product?.map 所以我的代碼現在運行良好。
問題陳述:我會給你三個非常好的方法,為了解決它,當 redux 將狀態轉移到組件時出現問題,所以看起來渲染比 props 對組件的響應更快。
因此,當您的 props 的值未定義時,您的應用程序就會崩潰。
注意:我將舉一個一般性示例,並向您展示如何避免此錯誤。
例如,我有一個組件,我想在其中渲染來自 redux 響應的數據(使用 mapPropsToState),我需要做的只是檢查它是否未定義,然后如果它未定義,我們需要使用條件(三元) if 和 else 語句的運算符。
//suppose you will get an address object from api ,which will contain city ,area ,street ,pin code etc
// address={} intially address is a blank object
render(){
return(
(typeof address.area!='undefined')?
<div>
<div>{address.city}</div>
<div>{address.street}</div>
<div>{address.pin_code}</div>
<div>{address.area}</div>
</div>
:<div>loading....</div>
)
}
另一種方法是簡單地使用 loadash 中的 loadash 包,您可以通過調用函數“isUndefined”來實現相同的目的,您也可以在 inputFields 中同樣使用它
<FloatingLabel label="Username">
<Form.Control
type="input"
placeholder=" "
name="username"
value={props.username}
defaultValue={_.isUndefined(props.userEditResponse)?'':props.userEditResponse.username}
required
onChange={(e)=>onInputchange(e)}
/>
</FloatingLabel>
//note: you can also use (typeof props.userEditResponse!='undefined')?'do somthing':'leave it'
loadash安裝:
npm i lodash 然后在您的組件中導入以下行,然后您可以使用它,就像我在上面的示例中使用的那樣。
import _ from 'lodash'
注意:答案只是給您一個想法,這確實是一個恐慌問題,這就是為什么我與你們分享它,它可能對你們中的許多人有所幫助,您可以在不同情況下使用類似的方式。 謝謝!
此外,您可以使用更多? :
這 ?。 運算符就像 . 鏈接運算符,除了如果引用為空(null 或未定義)時不會導致錯誤,表達式會短路並返回未定義的值。 與函數調用一起使用時,如果給定函數不存在,則返回 undefined。
當存在引用可能丟失的可能性時,當訪問鏈接屬性時,這會導致更短和更簡單的表達式。 當無法保證需要哪些屬性時,它在探索對象的內容時也很有幫助。
{ props.rolesListSuccessResponse?.permissions.map((list,index) => (
<div className="mb-3 col-md-3" key={index}>
<Form.Check
type={'checkbox'}
id={list.name}
label={list.name.charAt(0).toUpperCase()+list.name.slice(1)}
/>
</div>
))}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.